我写了一个程序来使用指针交换两个字符串。
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)来打印整个字符串(这很有意义),但令我惊讶的是上面的方法也有效(即使没有任何增加的指针值来打印下一个字符)。
有关上述问题的任何提示和建议将不胜感激。谢谢!
答案 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];