使用指针交换两个字符串会输出奇怪的输出

时间:2016-10-22 05:39:12

标签: c++ debugging c++11 pointers

我写了一个程序来使用指针交换两个字符串。

char *names[]={"Sachin","Kapil","Ajay","Sunil","Anil"};
cout<<"String II is ";cout<<names[1];
cout<<"\nString IV is ";cout<<names[3];
char *t;
t=names[1];
names[1]=names[3];
names[3]=t;
cout<<"\nString II is ";cout<<names[1];
cout<<"\nString IV is ";cout<<names[3];

在第一行中,我使用了一个char指针数组来存储字符串第一个字符的地址。

当我输入名字[1]和姓名[3]时:

打印整个字符串,但是不应该单独打印字符指针的地址吗?

此外,程序如何打印整个字符串而不是单独打印第一个字符?

编译完成后,我收到第1行的警告说: 警告:不推荐将字符串常量转换为'char *'[-Wwrite-strings] |

该程序按预期运行,但我很想知道它是如何工作的。我遇到了一个实现,他们使用cout.write(names [i],len)来打印整个字符串(这很有意义),但令我惊讶的是上面的方法也有效(即使没有任何增加的指针值来打印下一个字符)。

有关上述问题的任何提示和建议将不胜感激。谢谢!

2 个答案:

答案 0 :(得分:0)

首先 - 为什么你不只是获得地址输出。 当您将char*插入std::cout<<s;s其中char*类型为'\0'的流时,插入逻辑会假定s指向'C'的第一个字符串。 'C'字符串是以nul(std::cout<<static_cast<void*>(c);字符)结尾的一系列字符。 因此插入逻辑输出该系列字符。

如果您使用void*,则会得到不同的结果,因为<<指针的插入方式不同。

根据您插入的内容,对流上的const运算符进行了重载以执行不同的操作。

现在为什么你会收到警告。你正在发现C ++特别是从C继承的行李的一些不愉快的遗产。 在没有const修饰符的早期C的旧时代,没有办法表明在运行时无法修改字符串文字(例如“Sachin”),并且在不同的平台上这样做会产生不同的影响范围from harmlessy修改数据,抛出一个访问异常来修改代码中对该字符串值的所有文字引用(可能有几个)。

因此,当C ++出现并引入const char[](很快被C语言采用)时,人们认为在代码char[]中创建字符串文字的类型是合适的。但是有些编译器(当你设置错误时!)仍允许你将文字分配给char*(或fs.init() .then(() => fs.mkdir('dir')) .then(() => fs.writeFile('file.txt', 'hello world')) .then(() => fs.clear()) )以便向后兼容。 除非您维护古老的代码并且高级程序员已经指示您,否则不会启用该选项。

答案 1 :(得分:0)

流库识别char *类型并将其视为空终止的c样式字符串,它只是一个以null结尾的字符数组。

要使其打印地址,请输入将字符串转换为void *。

即。

cout << "String II is "; cout << (void *)names[1];

现在输出:

String II is 0x400a0b

至于为什么第一个字符不打印,这是因为流库将其视为空终止的C字符串。但是,如果你真的只想要打印第一个字符,你可以轻松地完成这个:

cout << "String II is "; cout << *names[1];

或:

cout << "String II is "; cout << names[1][0];

像你这样操纵指针是可以的,但操纵它们包含的内容并不像你拥有它们那样被声明。所以你应该真的把它们称为const。这也会删除编译警告。 所以代码就会变成。

const char *names[]={"Sachin","Kapil","Ajay","Sunil","Anil"};
cout << "\nString II is "; cout << (void*)names[1];
cout << "\nString IV is "; cout << (void*)names[3];

const char *t;
t = names[1];
names[1] = names[3];
names[3] = t;

cout << "\nString II is "; cout <<(void*)names[1];
cout << "\nString IV is "; cout <<(void*)names[3];