在C语言中初始化字符串;以下内容是否有用?

3

我知道在C语言中有两种不同的方法来初始化字符串。

char str[] = "abcd";

char str[] = {'a','b','c','d','\0' };

明显地,写"abcd"{'a','b','c','d','\0' }更省时间且更舒适。

我们能像最后一行那样初始化字符串的原因是什么?它在某些情况下有用还是多余的?


不,这没有意义。你展示的两行代码是__严格__等价的。 - Jabberwocky
1
第二种形式适用于任何聚合初始化。第一种形式是 char 数组的特殊情况。 - M.M
1
在这种情况下,它们是等效的,但是你不能使用char* str = {'a','b','c','d','\0' };,但是你可以使用char* str = "abcd";,因为后者首先创建一个未命名的数组,然后将str指针分配给它,而前者只是一个等待初始化为数组的字符列表。 - George
你的意思是,“使用它是毫无意义的吗?”还是“语言提供它是毫无意义的?”?语言提供它并不是毫无意义的,因为这显然是初始化任何类型数组的普通和通用方式。是否有用来初始化真正的字符串取决于你自己。(对我来说,我很少甚至从不使用它。) - Steve Summit
2个回答

5
一般情况下,没有区别。但是有一些高级例外,具体如下...
- 在某些情况下,您需要一个字符数组,它不是有效的C字符串——也就是说,不以null结尾。那么必须使用后一种形式。只有在非常特殊的情况下才需要这样的字符串:非常古老的Unix代码和某些嵌入式系统实现。 - 后一种形式的另一个优点是更好的转义序列。字符串字面值的转义序列有点问题。假设我想打印一个扩展符号,其代码为0xAA,然后是字符串"ABBA"。puts("\xAAABBA");不会编译,因为它将\x后面的所有内容都视为十六进制数。char str[] = {'\xAA','A','B','B','A','\0'}; puts(str);就可以正常工作。(不过您也可以将字符串字面值分成几部分,以达到相同的效果:"\xAA" "ABBA"。) - 使用字符串字面值进行初始化还存在C语言中微妙但严重的缺陷,参见这里:Inconsistent gcc diagnostic for string initialization

1
另一个为了兼容性引入的“语言缺陷”是这个:char *s = "hello"; - chqrlie

3
< p >"char str[] = {'a','b','c','d','\0' }"这种形式很少用于初始化真正的字符串,这是事实。 < /p > < p >我曾经写过一些代码来过滤生成的文本中意外的粗俗词汇,并且在自我审查时,我以一种不会冒犯任何未来维护程序员眼睛的方式初始化了要查找的单词数组:

char badwords[][5] = {
    { 's', 0x68, 105, 0164, '\0' },
    { 'p', 0151, 0x73, 115, '\0' },
    { 'c', 117, 0156, 0x74, '\0' },
    { 'f', 0x75, 0143, 107, '\0' },
    /* ... */
};

2
额外得分如果将其混合使用八进制、十进制和十六进制来更加混淆。 :-) - Ted Lyngmo
@SteveSummit:抱歉这么明确,那么对于非ASCII字符集的可移植性怎么样?我想不到任何简单的方法能达到相同的混淆水平。 - chqrlie
@chqrlie 别担心,我只是开玩笑的。或许我应该为没有认真回答你的问题而道歉!我也想不到什么简单的方法,最好的办法可能是一个方案,在这个方案中任何大写字母都要按照凯撒密码进行解密,注意要避免EBCDIC中的不连续性。也就是说,像char badwords[] = { "shiW", "piVs", "cXnW", "fXFk"}这样的东西,可以在运行时使用基于if(isupper(*p) *p = tolower(*p-3)的东西进行解码。(或者只使用rot13)。 - Steve Summit
1
@TedLyngmo 我不能独占荣誉——我从Sjörd Mullender在第一届IOCCC中获胜的作品中窃取了这个想法。 - Steve Summit
@SteveSummit:这样做是可行的,但仍然无法在所有潜在字符集上实现可移植性...如果在运行时解码可以接受,那么一个简单的排列可能就足够了。无论哪种情况,都不再是OP问题的说明 :) - chqrlie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接