为了账号安全,请及时绑定邮箱和手机立即绑定

字符串文字的C优化

字符串文字的C优化

C
天涯尽头无女友 2019-11-19 15:13:09
刚刚在gdb中检查了以下内容:char *a[] = {"one","two","three","four"};char *b[] = {"one","two","three","four"};char *c[] = {"two","three","four","five"};char *d[] = {"one","three","four","six"};我得到以下内容:(gdb) p a$17 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"}(gdb) p b$18 = {0x80961a4 "one", 0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four"}(gdb) p c$19 = {0x80961a8 "two", 0x80961ac "three", 0x80961b2 "four", 0x80961b7 "five"}(gdb) p d$20 = {0x80961a4 "one", 0x80961ac "three", 0x80961b2 "four", 0x80961bc "six"}等效词的字符串指针是相同的,我感到非常惊讶。我本以为每个字符串都会在堆栈上分配自己的内存,而不管它是否与另一个数组中的字符串相同。这是某种编译器优化的示例,还是这种字符串声明的标准行为?
查看完整描述

3 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

它称为“字符串池”。在Microsoft编译器中是可选的,但在GCC中则不是。如果关闭MSVC中的字符串池,则不同阵列中的“相同”字符串将被复制,并且具有不同的内存地址,因此将占用额外(不必要)的50字节左右的静态数据字节。


编辑:v 4.0之前的gcc有一个选项,-fwritable-strings该选项禁用了字符串池。此选项的作用是双重的:它允许覆盖字符串文字,并禁用字符串池。因此,在您的代码中,设置此标志将允许有些危险的代码


/* Overwrite the first string in a, so that it reads 'xne'.  Does not */ 

/* affect the instances of the string "one" in b or d */

*a[0] = 'x';


查看完整回答
反对 回复 2019-11-19
?
倚天杖

TA贡献1828条经验 获得超3个赞

(我假设你a,b,c并d声明为局部变量,这是你的筹码相关预期的原因。)


C中的字符串文字具有静态存储持续时间。它们永远不会被“分配”在栈上。它们始终分配在全局/静态存储器中,并且“永远存在”,即只要程序运行即可。


您a,b,c和d数组被分配在堆栈中。存储在这些数组中的指针指向静态内存。在这种情况下,相同单词的指针相同并没有什么异常。


编译器是否将相同的文字合并为一个取决于编译器。一些编译器甚至具有控制此行为的选项。字符串文字始终是只读的(这就是为什么最好const char *在数组中使用类型的原因),因此,在您开始依赖实际指针值之前,是否合并它们不会有太大的区别。


PS只是出于好奇:即使将这些字符串文字分配在堆栈上,您为什么也希望相同的文字多次被“实例化”?


查看完整回答
反对 回复 2019-11-19
?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

据我所知,对同一字符串文字的两个(或更多)引用必须解析为相同的内存位置。即使有些是“重复的”,编译器也可以(有些确实)为每个字符串文字分配存储空间。

查看完整回答
反对 回复 2019-11-19
  • 3 回答
  • 0 关注
  • 433 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信