为什么我可以在使用双引号声明时将指针用作字符串,而不是在C中使用花括号?

Jaw*_*Mmm 28 c string pointers

如果我声明并使用这样的指针:

int counter;
char *pCow = "pCow goes MOO";

for(counter = 0; counter < 14; counter++)
    printf("%c", pCow[counter]);
Run Code Online (Sandbox Code Playgroud)

它显示整个字符串并且工作,是的,并且有很多欢乐.

但是,如果我使用这样的初始化器:

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]);
Run Code Online (Sandbox Code Playgroud)

程序崩溃了,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
Run Code Online (Sandbox Code Playgroud)

在Eclipse CDT中经过精心测试.

Dao*_*Wen 40

在这种情况下,pCow设置为静态内存中c字符串的地址:

char *pCow = "pCow goes MOO";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,pCow设置为值'p'(即112):

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
Run Code Online (Sandbox Code Playgroud)

由于地址112很可能指向受限/无效的内存,因此当您尝试访问时会导致程序爆炸pCow[counter].

警告"标量初始化程序中的多余元素"告诉您,'p'由于指针只需要一个值,因此忽略了所有内容.

警告"初始化使得指针来自没有强制转换的整数"告诉你,你正在使用它'p'作为指针,这可能不是一个好主意......

如果要使用初始化程序语法,您要做的是声明pCow字符数组而不是字符指针:

char pCow[] = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
Run Code Online (Sandbox Code Playgroud)

  • @JawiMmm - 是的,[他们故意这样做](http://meta.stackexchange.com/questions/50697/time-limit-on-accepting-an-answer).无论如何,我很高兴这对你有所帮助!另外,[使用`char*`指向c字符串文字也不是一个好主意](http://stackoverflow.com/questions/16767042/deprecated-conversion-from-string-constant -to-char-in-c?lq = 1)(你应该使用`const char*`代替). (2认同)
  • 在GCC中你可以这样写:`char*pCow =(char []){'p','C','o','w','','g','o','e' ,'s','','M','O','O','\ 0'};`.这样你就有了一个指向存储在静态存储器中的数组的指针,它与使用引号相同.但是,这种语法不仅可以使用方便的字符数组. (2认同)
  • @aragaer语法是标准C的一部分 (2认同)

Lun*_*din 11

"pCow goes MOO"是一个字符串文字,有两种不同的用途.您可以将它用作数组的初始值设定项:

char aCow[] = "pCow goes MOO";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,字符串文字的内容将复制到数组中.

或者,您可以在程序的任何位置使用字符串文字作为独立常量数组.例如strcpy(cow, "pCow goes MOO");.所以这两者之间有明显的区别:

char aCow[] = "pCow goes MOO";
char* pCow  = "pCow goes MOO";
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,文字被复制到数组中.在第二种情况下,文字在只读内存中仍然是一个独立的常量,我们用指针指向它.前者可以修改,后者不可以.

至于的情况

char *pCow = {'p','C','o','w',' ','g','o','e','s',' ','M','O','O','\0'};
Run Code Online (Sandbox Code Playgroud)

您正在使用指针,但您没有字符串文字.相反,您有一个用于数组的初始化列表.一个好的编译器会警告你"多余的初始化程序".例如,代码编译的原因是C中的一个非常奇怪的规则,它允许使用大括号初始化普通变量int x = {1};.因此编译器使用此规则初始化指向地址的指针'p',这当然是无意义的,然后它会丢弃初始化列表的其余部分.