【1】 "abcdef"一定是常量吗?
依情况而定。
(1)不是常量的情况。当“abcdef”作为字符数组初始值时就不是常量。
示例代码如下:
char str[] = "abcdef";
//或者
char str[] ={"abcdef"};
以字符串形式出现的,编译器都会为该字符串自动添加一个0作为结束符,如在代码中写"abcdef",那么编译器帮你存储的是"abcdef "。
所以上面语句最终的结果是:
char str = {'a', 'b', 'c', 'd', 'e', 'f',' '};
可以查看一下。如图所示:
扩展:如果char str[] = "abcdef";是在函数内部写的话,那么这里 的"abcdef "因为不是常量,所以应该被放在栈上。
(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 "被放在常量区中,但是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[]="