本人是一个新手,刚刚自学完C++, 今天有感而发,突然想到想到一个问题,关于cin对于字符数组的输入,具体的代码描述是这样的:
(OS: CentOS 7, clang++)
1 #include <iostream> 2 using std::cin; 3 using std::cout; 4 using std::endl; 5 6 int main(void) 7 { 8 char str[6] = "Hello"; 9 10 cout << str << endl; 11 cout << &str[0] << endl; 12 cout << &str << endl; 13 14 cin >> str; 15 cout << str << endl;16 cout << &str << endl; 17 18 return 0; 19 }
运行结果:
1 Hello 2 Hello 3 0x7fffcb2c8786 4 World //此为输入 5 World 6 World 7 0x7fffcb2c8786
我觉得这反映了一些深刻的问题:
1:代码的第10行和第11行,我本想输出数组的第一个元素的地址,但为什么输出了整个数组?
2:为什么12行和16行的结果一样,字符串常量"Hello"不是应该存储在常量区么?
3:如果第8行改为 char *str = "Hello"; 或 char str[] = "Hello",
对于后者,
clang++ 10.cpp -o main
10.cpp:8:14: warning: conversion from string literal to 'char *' is deprecated [-Wc++11-compat-deprecated-writable-strings]
char *str = "Hello";
^
1 warning generated.
编译会发出警告,并且运行到第14行出现段错误,这两种表达式的内存分配方式有何异同。
4:对于C语言:
1 #include <stdio.h> 2 3 int main(void) 4 { 5 char str[] = "Hello"; 6 7 printf("%s\n", str); 8 printf("%s\n", &str[0]); 9 printf("%p\n", str); 10 11 return 0; 12 }
为什么第7、8行的结果一样? %s有什么内涵?
clang编译报警:clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated
g++不报警告
先解释一下问题3:
1 int main(void) 2 { 3 char *str1="233345";//"233345"存储在文字常量区,str1为指向那个的首地址的指针,编译器认为str1指向内容不应当被修改,而str1类型不是const,所以爆warning 4 const char* strtmp1="233345";//这样就不会爆warning 5 //char str3[];//编译不通过 6 char str[]="233345";//存储在栈上,根据用来初始化的字符串长度自动确定数组长度为7 7 char str2[7]="233345";//存储在栈上 8 str[1]='1';//可以 9 str2[1]='1';//可以 10 //str1[1]='1';//段错误 11 return 0; 12 }
参考:http://blog.csdn.net/codingkid/article/details/6858395
http://blog.csdn.net/xyy410874116/article/details/6397549
对于第二个问题,从上面的参考资料可以得知,这样定义char str[6]=".....";得到的是一个字符数组,数组内内容被初始化为了".....",也就是str中的"....."是存储在栈上的而不是常量区。
对于第四个问题,我想C内部printf("%s")的实现应该类似于这样(只是示意,当然不是真的实现)
void my_out(const char *t) { for(;*t!='\0';t++) putchar(*t); }
这是由于C约定合法字符串最后有'\0'。因此:
int main() { char str[] = "Hello";//str初始化用的"Hello"字符串最后会自动添加'\0' char wstr = 't';//wstr只是一个字符,自然不会有'\0' char wstr2[5]="Hell"; wstr2[4]='o';//wstr2最后缺少'\0' printf("%s\n",str); //printf("%s\n",wstr);//段错误 //printf("%s\n",wstr2);//段错误,也可能没有,反正运行不正常就是了 return 0; }
对于第一个,
参考一下https://www.zhihu.com/question/52252124
就是c++的cout如果接受到指向字符的指针,就会用跟C处理printf("%s")类似的方式去做。
因此:
char ch='1'; cout<<&ch;
就会出现奇怪的事情。
11行传的就是一个指向字符(str[0])的指针。
10行由于c/c++不支持直接以数组作为参数,str降阶成了&str[0]。(事实上cout字符数组的时候,这样的方式才是正常的吧...)
12行传去的是一个指向一个字符数组的指针。
跪谢!Thank you very much!!!