【1】 "abcdef"一定是常量吗?
依情况而定。
(1)不是常量的情况。当“abcdef”作为字符数组初始值时就不是常量。
示例代码如下:
char str[] = "abcdef"; //或者 char str[] ={"abcdef"};
以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写"abcdef",那么编译器帮你存储的是"abcdef\0"。
所以上面语句最终的结果是:
char str = {'a', 'b', 'c', 'd', 'e', 'f','\0'};
可以查看一下。如图所示:
扩展:如果char str[] = "abcdef";是在函数内部写的话,那么这里 的"abcdef\0"因为不是常量,所以应该被放在栈上。
(2)是常量的情况。当把字符串赋值于一个字符指针变量时。
示例代码如下:
char *ptr = "abcdef";
因为定义的是一个普通指针,并没有定义空间来存放"abcdef",所以编译器得帮我们找地方来放"abcdef"。
显然,把这里的"abcdef"当成常量并把它放到程序的常量区是编译器最合适的选择。
所以,尽管ptr的类型不是const char *,并且ptr[0] = 'x';也能编译通过,但是执行ptr[0] = 'x';就会发生运行时异常。
因为这个语句试图去修改程序常量区中的东西。
记得哪本书中曾经说过char *ptr = "abcdef";这种写法原来在c++标准中是不允许的,但是因为这种写法在c中实在是太多了,为了兼容c,不允许也得允许。
虽然允许,但是建议的写法应该是const char* ptr = "abcdef";
这样如果后面写ptr[0] = 'x'的话编译器就不会让它编译通过,也就避免了上面说的运行时异常。
再扩展一下,如果char* ptr = "abcdef";写在函数体内,那么虽然这里的"abcdef\0"被放在常量区中,但是ptr本身只是一个普通的指针变量,
所以ptr是被放在栈上的,只不过是它所指向的东西被放在常量区罢了。
【2】字符串常量的类型怎么分析?
可以理解为相应字符常量数组的类型。如"abcdef"的类型就可以看成是const char[7]。
【3】数组参数如何理解?
对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型。
如对于函数
void func(char sa[100], int ia[20], char *p)
则sa的类型为char*,ia的类型为int*,p的类型为char*。
【4】关于以上理论分析的相关示例代码如下:
1 #include<iostream> 2 #include<string.h> 3 using namespace std; 4 char st[]={'a','b','c','d','e','f'}; 5 char *pt="abcdef"; 6 7 char s[10]={'a','b','c','d','e','f'}; 8 char ss[10]; 9 10 char ch1[]={"abcdef"}; 11 char ch2[]="abcdef"; 12 13 char p[10]={"abcdef"}; 14 char pr[10]="abcdef"; 15 16 char st3[]="\0"; 17 char *st4="\0"; 18 void main() 19 { 20 cout<<"sizeof(st)="<<sizeof(st)<<endl; // 6 21 cout<<"strlen(st)="<<strlen(st)<<endl; // 6 22 cout<<"sizeof(pt)="<<sizeof(pt)<<endl; // 4 23 cout<<"strlen(pt)="<<strlen(pt)<<endl; // 6 24 25 char str[]={'a','b','c','d','e','f'}; 26 char *ptr="abcdef"; 27 cout<<"sizeof(str)="<<sizeof(str)<<endl; // 6 28 cout<<"strlen(str)="<<strlen(str)<<endl; // 11 //不确定 29 cout<<"sizeof(ptr)="<<sizeof(ptr)<<endl; // 4 30 cout<<"strlen(ptr)="<<strlen(ptr)<<endl; // 6 31 32 33 cout<<"sizeof(s)="<<sizeof(s)<<endl; // 10 34 cout<<"strlen(s)="<<strlen(s)<<endl; // 6 35 cout<<"sizeof(ss)="<<sizeof(ss)<<endl; // 10 36 cout<<"strlen(ss)="<<strlen(ss)<<endl; // 0 37 38 39 char sr[10]={'a','b','c','d','e','f'}; 40 char ssr[10]; 41 cout<<"sizeof(sr)="<<sizeof(sr)<<endl; // 10 42 cout<<"strlen(sr)="<<strlen(sr)<<endl; // 6 43 cout<<"sizeof(ssr)="<<sizeof(ssr)<<endl; // 10 44 cout<<"strlen(ssr)="<<strlen(ssr)<<endl; // 18 //不确定 45 46 47 cout<<"sizeof(ch1)="<<sizeof(ch1)<<endl; // 7 48 cout<<"strlen(ch1)="<<strlen(ch1)<<endl; // 6 49 cout<<"sizeof(ch2)="<<sizeof(ch2)<<endl; // 7 50 cout<<"strlen(ch2)="<<strlen(ch2)<<endl; // 6 51 52 char chr1[]={"abcdef"}; 53 char chr2[]="abcdef"; 54 cout<<"sizeof(chr1)="<<sizeof(chr1)<<endl; // 7 55 cout<<"strlen(chr1)="<<strlen(chr1)<<endl; // 6 56 cout<<"sizeof(chr2)="<<sizeof(chr2)<<endl; // 7 57 cout<<"strlen(chr2)="<<strlen(chr2)<<endl; // 6 58 59 cout<<"sizeof(p)="<<sizeof(p)<<endl; // 10 60 cout<<"strlen(p)="<<strlen(p)<<endl; // 6 61 cout<<"sizeof(pr)="<<sizeof(pr)<<endl; // 10 62 cout<<"strlen(pr)="<<strlen(pr)<<endl; // 6 63 64 char pp[10]={"abcdef"}; 65 char ppr[10]="abcdef"; 66 67 cout<<"sizeof(pp)="<<sizeof(pp)<<endl; // 10 68 cout<<"strlen(pp)="<<strlen(pp)<<endl; // 6 69 cout<<"sizeof(ppr)="<<sizeof(ppr)<<endl; // 10 70 cout<<"strlen(ppr)="<<strlen(ppr)<<endl; // 6 71 72 73 cout<<"sizeof(st3)="<<sizeof(st3)<<endl; // 2 74 cout<<"strlen(st3)="<<strlen(st3)<<endl; // 0 75 cout<<"sizeof(st4)="<<sizeof(st4)<<endl; // 4 76 cout<<"strlen(st4)="<<strlen(st4)<<endl; // 0 77 78 char s3[]="\0"; 79 char *s4="\0"; 80 cout<<"sizeof(s3)="<<sizeof(s3)<<endl; // 2 81 cout<<"strlen(s3)="<<strlen(s3)<<endl; // 0 82 cout<<"sizeof(s4)="<<sizeof(s4)<<endl; // 4 83 cout<<"strlen(s4)="<<strlen(s4)<<endl; // 0 84 }
希望仔细分析,有所收获。