在C语言中初始化字符数组,哪种方法更好?

4
以下是初始化字符数组的两种方式:
char charArray1[] = "foo";
char charArray2[] = {'f','o','o','\0'};

如果两者等效,我们预期每个人都会使用上述第一种选项(因为它需要较少的按键)。但是我看到过作者始终使用第二种方法的代码。
我猜测,在第一种情况下,字符串“foo”存储在数据段中,并在运行时复制到数组中,而在第二种情况下,字符存储在代码段中,并在运行时复制到数组中。由于某些原因,作者对数据段中的任何内容过敏。
编辑:假设这些数组在函数内部声明。
问题:我的推理正确吗?你更喜欢哪种风格?为什么?

第一种风格肯定更清晰、更简洁。在我看来,相比可读性的好处,1和2之间的性能影响可以忽略不计。 - obelix
3
好的,我会尽力完成翻译任务。以下是需要翻译的内容:相关链接:https://dev59.com/bU_Ta4cB1Zd3GeqPCJvm 和 http://stackoverflow.com/questions/3429071/string-initializer-and-read-only-section。区别在于,使用大括号初始化时,数组中的每个元素都将按照给定的值进行初始化;而使用圆括号则只能将第一个元素初始化为给定值,其余元素将被初始化为0。关于字符串也有类似的情况,使用大括号可以将每个字符都初始化为给定值,而使用双引号则只能初始化整个字符串。此外,使用大括号初始化将数据存储在可写区域,而使用双引号或圆括号则将数据存储在只读区域。 - Prasoon Saurav
@Prasoon 感谢提供链接。在发布之前,我已经使用谷歌和搜索了SO,但是没有找到它。 - Dheeraj Vepakomma
2个回答

5
另一个可能性是什么呢:
char charArray3[] = {102, 111, 111, 0};

您不应该忘记,C char类型是一种数字类型,它只是经常被用作char代码的值。但是,如果我使用数组与文本无关的内容,我肯定会更喜欢使用上述语法对其进行初始化,而不是将其编码为字母并将其放在引号之间。

如果您不想要终端0,则还必须使用第二种形式或在C中使用:

char charArray3[3] = "foo";

这是一个几乎没有人知道的C语言特性,但如果编译器在初始化charArray时没有足够的空间来存放最后的0,它就不会放置,但代码是合法的。然而,应该避免使用这个特性,因为它已经从C++中移除了,C++编译器会产生错误。
我检查了由gcc生成的汇编代码,所有不同形式的代码都是等效的。唯一的区别是它使用.string或.byte伪指令来声明数据。但这只是一个可读性问题,在结果程序中不会有任何区别。

1

我认为第二种方法主要用于旧代码中,编译器不支持第一种方法。两种方法都应该将数据存储在数据段中。由于可读性,我更喜欢第一种方法。另外,我曾经需要修补一个程序(记不清是哪个了,它是一个标准的UNIX工具),使其不使用/etc(这是为嵌入式系统)。因为他们使用了第二种方法,我的grep无法找到“etc”的正确位置,所以我花了很长时间才找到。


1
哪些编译器“不支持第一种方法”?它是严格的C89,每个ANSI编译器都应支持此方法。 - user411313
如果你想保存一些文本,使用字符数组是不错的选择。但如果你想存储数字,"\x66\x6f\x6f" 显然比 {102, 111, 111, 0} 难以阅读(甚至需要进行十六进制或十进制转换,因为你无法使用十进制输入字符代码)。在某些情况下,放弃第二种形式会带来真正的痛苦。 - kriss
@gordongekko:我原本以为K&R C在使用nice方法时会出现问题,但是一些搜索似乎表明即使是K&R C也支持这两种方法... - DarkDust
@kriss:我并不是说第二种形式在一般情况下是个坏主意,但如果你真的想存储文本,那么这是一个坏主意。{'/', 'e', 't', 'c', 0}"/etc"确实更难读/找到,你同意吗? - DarkDust
我完全同意。我只是想指出,对于某些用例而言最佳解决方案可能会成为另一个用例的问题。使用适合你所做的风格。 - kriss

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