为什么我可以在用双引号声明时使用指针作为字符串,而不是在C中用花括号括起来?
如果我声明并使用这样的指针:
int counter; char *pCow = "pCow goes MOO"; for(counter = 0; counter < 14; counter++) printf("%c", pCow[counter]);
它显示整个字符串并且工作,是的,并且有很多欢乐。
但是,如果我使用这样的初始化器:
int counter; char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'}; for(counter = 0; counter < 14; counter++) printf("%c", pCow[counter]);
程序崩溃了,pCow拒绝为我的享乐主义乐趣而呻吟!
3 Warnings. 0 Errors line 11 (near initialization for 'pCow') [enabled by default] C/C++ Problem line 11 excess elements in scalar initializer [enabled by default] C/C++ Problem line 11 initialization makes pointer from integer without a cast [enabled by default] C/C++ Problem
在Eclipse CDT中经过精心测试。
在这种情况下, pCow
设置为静态内存中c字符串的地址:
char *pCow = "pCow goes MOO";
在这种情况下, pCow
设置为值'p'
(即112
):
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
由于地址112
很可能指向受限/无效的内存,因此当您尝试访问pCow[counter]
时,会导致程序爆炸。
警告“标量初始化程序中的多余元素”告诉您它忽略了'p'
之后的所有内容,因为指针只需要一个值。
警告“初始化使得指针来自没有强制转换的整数”告诉你你正在使用'p'
作为指针,这可能不是一个好主意……
如果要使用初始化程序语法,您要做的是将pCow
声明为字符数组而不是字符指针 :
char pCow[] = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
"pCow goes MOO"
是一个字符串文字,有两种不同的用途。 您可以将它用作数组的初始值设定项:
char aCow[] = "pCow goes MOO";
在这种情况下,字符串文字的内容将复制到数组中。
或者,您可以在程序的任何位置使用字符串文字作为独立常量数组。 例如strcpy(cow, "pCow goes MOO");
。 所以这两者之间有明显的区别:
char aCow[] = "pCow goes MOO"; char* pCow = "pCow goes MOO";
在第一种情况下,文字被复制到数组中。 在第二种情况下,文字在只读存储器中仍然是一个独立的常量,我们用指针指向它。 前者可以修改,后者不可以。
至于的情况
char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
您正在使用指针,但您没有字符串文字。 相反,您有一个用于数组的初始化列表。 一个好的编译器会警告你“过多的初始化程序”。 代码编译的原因是C中的一个非常奇怪的规则,它允许使用大括号初始化普通变量,例如int x = {1};
。 因此,编译器使用此规则初始化指向指向地址'p'
指针,这当然是无意义的,然后它会丢弃初始化列表的其余部分。