C

时间:2018-05-23 14:05:02

标签: c

关于字符串文字的静态生命周期,本网站有很多好的答案。据我了解,它们被分配在只读内存中(其他人专门提到了“字符串 - 文字池”)。因此,返回指向字符串文字的指针不会导致悬空指针。它们也是左值。

为什么同样不适用于整数常量字面值?它是否也没有静态存储时间?如果我尝试分配一个整数常量,gcc会抱怨它不是左值。

为什么字符串文字给予这种特殊处理? (和C99中的复合文字)。我已经听到了左值的以下定义:“左值(定位符值)表示占据内存中某些可识别位置的对象(即有一个地址)。”如果字符串文字(字符数组类型)必须在内存中可寻址,为什么同样不适用于整数?甚至整数仍然必须在程序的地址空间中分配。有性能原因吗?

3 个答案:

答案 0 :(得分:5)

整数常量字面值左值(参见C标准n1570 §6.3.2.1),并且(或者可能是因为)通常甚至不在可寻址内存中。但是,字符串文字是不应修改的左值(§6.4.5)(否则为undefined behavior)。

在许多情况下,足够小的整数文字被转换为单个机器代码指令的子部分,并且没有任何位置。

对于一些愚蠢的例子,int zero(void) { return 0; }被编译(在Linux / x86-64 / Debian上使用GCC 8.1)和gcc -O2 -S -fverbose-asm进入

    .globl  zero
    .type   zero, @function
zero:
.LFB0:
    .cfi_startproc
# zero.c:1: int zero(void) {return 0;}
    xorl    %eax, %eax  #
    ret 
    .cfi_endproc

您在生成的机器代码中没有看到0的任何提及!

当然,有关整数文字实现的详细信息显然是特定于实现的。它们取决于指令集架构,优化级别,编译器版本,月亮阶段,我的猫的情绪(我不确定最后两个项目,我让你去检查)。

答案 1 :(得分:2)

C字符串文字是左值的原因是因为它们在技术上是char []类型的数组,并且数组总是必须在内存中可寻址。

如果你问为什么,我最好的猜测是因为文字是左值是没有意义的,但是因为无论如何都无法分配数组,所以没有必要明确地打扰在这种情况下(字符串文字)禁止它作为左值。可能有一个更完整的解释,有人对编译器的构造能够提供更多知识。

答案 2 :(得分:2)

  

为什么同样不适用于整数常量字面值?可以   还没有静态存储时间?

整数常量不是标准术语中的“文字”。 “常数”是一个单独的东西。不,常量没有静态存储持续时间,因为它们根本不是对象。它们是常数。 C没有将它们定义为具有任何类型的存储。实际上,它们通常直接表示在生成的可执行代码中,而不是程序数据中。

  

如果我尝试分配给   整数常量,gcc抱怨它不是左值。

不是。换句话说,常量不对应于内存位置,它只是一个常量。

  

为什么字符串文字给予这种特殊处理? (和复合   C99中的文字。)

字符串和复合文字的处理并不特别,它就是它的本质。你似乎对错误地认为这些类型的对象文字对常量是类似的东西感到困惑,但事实并非如此。字符串和复合文字表示在内存中具有表示形式的对象。

  

我听说过以下关于左值的定义:“An   lvalue(locator value)表示占用某些对象的对象   内存中可识别的位置(即有一个地址)。“

  

如果是一个字符串   literal(字符数组类型)必须在内存中可寻址,为什么   是否同样不适用于整数?

你再次瞥了一眼。整数可以并且经常在内存中具有可寻址的位置。但是整数常量不会(或者至少C不要求它们具有)。它们在程序中的表示通常是可执行代码。

术语“文字”的部分重要性在于,如此描述的实体代表了指定类型的实际对象

另一方面,“常量”表示指定类型的

  

即使是整数仍然必须   在程序的地址空间中分配。

这里有一个微妙的区别,但在对象和价值之间是一个重要的区别。对象用存储位置标识;他们拥有和/或包含值。因此,整数类型的对象确实具有存储,并且表达式指定存储是左值。另一方面,虽然特定的整数值实际上可能是任意数量的对象的值,但值本身并不固有地与特定的存储位置相关联。

  

有表演吗?   原因是什么?

从根本上说,有语言设计的原因。其中一些确实提升了性能 - 即值可以直接编码为可执行的机器代码,而不是必须从(其他)内存加载它们的机器代码 - 但我不认为它们是主要因素。 / p>