有人质疑C ++中字符串文字的数据类型。
很多人都引用了这个标准:
窄字符串文字的类型为“n const char数组”,其中n是下面定义的字符串大小,并且具有静态存储持续时间(3.7)
我在main函数中写了以下语句:
char cstring[]= "hellohellohellohellohellohello";
但我找不到任何字符串文字作为静态数据存储在程序集中。事实上,程序集显示字符串被分解并直接“存储”在指令中。
movl $1819043176, -48(%rbp)
movl $1818585199, -44(%rbp)
movl $1701343084, -40(%rbp)
movl $1752132716, -36(%rbp)
movl $1869376613, -32(%rbp)
movl $1819043176, -28(%rbp)
movl $1818585199, -24(%rbp)
movw $28524, -20(%rbp)
movb $0, -18(%rbp)
虽然全局范围中的类似语句因此将字符串存储为静态数据。
char cstring1[] = "hellohellohellohellohellohello";
集会
cstring1:
.string "hellohellohellohellohellohello"
以上示例可在线获取here。
所以这似乎不符合引用的标准。也许这里引用的内容有一些例外吗?
答案 0 :(得分:21)
它符合标准,在" as-if"规则。
由于字符串文字的唯一用途是初始化cstring
,因此不需要任何对象表示。编译器已经删除了它,支持通过具有相同结果的替代方法初始化cstring
,但编译器在某些方面(速度或代码大小)决定更好。
答案 1 :(得分:9)
表达式有类型。字符串文字如果用作表达式,则具有类型。 你的不是。
请考虑以下代码:
#include <stdio.h>
#define STR "HelloHelloHello"
char global[] = STR;
int main(void)
{
char local[] = STR;
puts(STR);
}
此程序中有三个字符串文字使用相同的标记形成,但它们的处理方式不同。
第一个是global
的初始化器,是具有静态生存期的对象的静态初始化的一部分。根据3.6.2节,静态初始化不必在运行时进行;编译器可以安排在二进制映像中预先格式化结果,以便进程在已经存在的数据的情况下开始执行,并且在此处已经完成。以与local[]
相同的方式初始化此对象也是合法的,只要它在全局变量动态初始化开始之前执行。
第二个是local
的初始化器,是一个字符串文字,但它实际上不是表达式。它是根据8.5.2的特殊规则处理的,该规则规定字符串文字中的字符独立用于初始化数组元素;字符串文字不用作单位。此对象具有动态初始化,从而导致在运行时加载值。
第三个是puts()
调用的参数,实际上确实使用字符串文字作为表达式,它将具有类型const char[N]
,该调用将衰减到const char*
。如果你真的想学习用于处理字符串文字的运行时类型的目标代码,你应该在表达式中使用文字,就像这个函数调用一样。
答案 2 :(得分:0)
我认为您引用的定义必须解释为引用其存储位置未显式声明的字符串文字,例如printf()
中的格式表达式。为了使这些代码有效,这些字符串文字必须存储在某处;如果无法从上下文中推断出定义,则定义指定它们的存储位置。
旁注:main()
中的字符串文字不会显示为静态数据,因为函数中声明的变量默认为“自动”。如果您改为编写static char cstring[]=...
,那么将在与cstring1[]
相同的位置看到它。
另一件事:存储位置不属于数据类型!