1.
以字符串形式出现的,编译器都会为该字符串自动添加一个
0
作为结束符,如在代码中写
"abc",
那么编译器帮你存储的是
"abc\0"
2."abc" 是常量吗?答案是有时是,有时不是。
不是常量的情况 :
"abc" 作为字符数组初始值的时候就不是,如 char str[] = "abc"; 因为定义的是一个字符数组,所以就相当于定义了一些空间来存放 "abc" ,而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为 char str[3] = {'a','b','c'}; 又根据上面的总结 1 ,所以 char str[] = "abc"; 的最终结果是 char str[4] = {'a','b','c','\0'}; 做一下扩展,如果 char str[] = "abc"; 是在函数内部写的话,那么这里的 "abc\0" 因为不是常量,所以应该被放在栈上。
是常量的情况
把 "abc" 赋给一个字符指针变量时,如 char* ptr = "abc"; 因为定义的是一个普通指针,并没有定义空间来存放 "abc" ,所以编译器得帮我们找地方来放 "abc" ,显然,把这里的 "abc" 当成常量并把它放到程序的常量区是编译器最合适的选择。所以尽管 ptr 的类型不是 const char* ,并且 ptr[0] = 'x'; 也能编译通过,但是执行 ptr[0] = 'x'; 就会发生运行时异常,因为这个语句试图去修改程序常量区中的东西。记得哪本书中曾经说过 char* ptr = "abc"; 这种写法原来在 c++ 标准中是不允许的,但是因为这种写法在 c 中实在是太多了,为了兼容 c ,不允许也得允许。虽然允许,但是建议的写法应该是 const char* ptr = "abc"; 这样如果后面写 ptr[0] = 'x' 的话编译器就不会让它编译通过,也就避免了上面说的运行时异常。又扩展一下,如果 char* ptr = "abc"; 写在函数体内,那么虽然这里的 "abc\0" 被放在常量区中,但是 ptr 本身只是一个普通的指针变量,所以 ptr 是被放在栈上的 , 只不过是它所指向的东西被放在常量区罢了。
3. 数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的。
如 char s1[3] 和 char s2[4] , s1 的类型就是 char[3] , s2 的类型就是 char[4], 也就是说尽管 s1 和 s2 都是字符数组,但两者的类型却是不同的。
4 . 字符串常量的类型可以理解为相应字符常量数组的类型,如 "abcdef" 的类型就可以看成是 const char[7]
5 .sizeof 是用来求类型的字节数的。如 int a; 那么无论 sizeof(int) 或者是 sizeof(a) 都是等于 4 ,因为 sizeof(a) 其实就是 sizeof(type of a)
6 . 对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型,如对于 void func(char sa[100],int ia[20],char *p) 则 sa 的类型为 char* , ia 的类型为 int* , p 的类型为 char*
转自 crazy wind`s blogs
2."abc" 是常量吗?答案是有时是,有时不是。
不是常量的情况 :
"abc" 作为字符数组初始值的时候就不是,如 char str[] = "abc"; 因为定义的是一个字符数组,所以就相当于定义了一些空间来存放 "abc" ,而又因为字符数组就是把字符一个一个地存放的,所以编译器把这个语句解析为 char str[3] = {'a','b','c'}; 又根据上面的总结 1 ,所以 char str[] = "abc"; 的最终结果是 char str[4] = {'a','b','c','\0'}; 做一下扩展,如果 char str[] = "abc"; 是在函数内部写的话,那么这里的 "abc\0" 因为不是常量,所以应该被放在栈上。
是常量的情况
把 "abc" 赋给一个字符指针变量时,如 char* ptr = "abc"; 因为定义的是一个普通指针,并没有定义空间来存放 "abc" ,所以编译器得帮我们找地方来放 "abc" ,显然,把这里的 "abc" 当成常量并把它放到程序的常量区是编译器最合适的选择。所以尽管 ptr 的类型不是 const char* ,并且 ptr[0] = 'x'; 也能编译通过,但是执行 ptr[0] = 'x'; 就会发生运行时异常,因为这个语句试图去修改程序常量区中的东西。记得哪本书中曾经说过 char* ptr = "abc"; 这种写法原来在 c++ 标准中是不允许的,但是因为这种写法在 c 中实在是太多了,为了兼容 c ,不允许也得允许。虽然允许,但是建议的写法应该是 const char* ptr = "abc"; 这样如果后面写 ptr[0] = 'x' 的话编译器就不会让它编译通过,也就避免了上面说的运行时异常。又扩展一下,如果 char* ptr = "abc"; 写在函数体内,那么虽然这里的 "abc\0" 被放在常量区中,但是 ptr 本身只是一个普通的指针变量,所以 ptr 是被放在栈上的 , 只不过是它所指向的东西被放在常量区罢了。
3. 数组的类型是由该数组所存放的东西的类型以及数组本身的大小决定的。
如 char s1[3] 和 char s2[4] , s1 的类型就是 char[3] , s2 的类型就是 char[4], 也就是说尽管 s1 和 s2 都是字符数组,但两者的类型却是不同的。
4 . 字符串常量的类型可以理解为相应字符常量数组的类型,如 "abcdef" 的类型就可以看成是 const char[7]
5 .sizeof 是用来求类型的字节数的。如 int a; 那么无论 sizeof(int) 或者是 sizeof(a) 都是等于 4 ,因为 sizeof(a) 其实就是 sizeof(type of a)
6 . 对于函数参数列表中的以数组类型书写的形式参数,编译器把其解释为普通的指针类型,如对于 void func(char sa[100],int ia[20],char *p) 则 sa 的类型为 char* , ia 的类型为 int* , p 的类型为 char*
转自 crazy wind`s blogs