C++字符串字面值的类型

5

出于好奇,我想知道 C++ 字符串字面值的真实底层类型。

根据我的观察,我得到了不同的结果。

类似以下的 typeid 测试:

std::cout << typeid("test").name() << std::endl;

请显示给我char const[5]

尝试将字符串字面值分配给不兼容的类型,如下所示(以查看给定的错误):

wchar_t* s = "hello";

我从VS12的智能感知中得到了一个值为“const char *”类型的值,无法用于初始化“wchar_t *”类型实体。

但我不明白它怎么可能是“const char *”,因为以下行在VS12中被接受:

char* s = "Hello";

我已经阅读过,这在C++11标准之前是允许的,因为它是为了与C进行兼容,尽管修改s将导致未定义的行为。 我认为这只是VS12尚未实现所有C++11标准,这一行通常会导致错误。
阅读C99标准(从这里,6.4.5.5)建议它应该是一个数组:
多字节字符序列然后用于初始化具有静态存储期和长度的数组,仅足以包含该序列。
那么,C ++字符串文字下面的类型是什么?
非常感谢您宝贵的时间。

5
VS12使用一种奇怪的方言,它与C++相似但并不完全相同。 - Kerrek SB
3个回答

8

字符串字面值的类型确实是const char[SIZE],其中SIZE是字符串长度加上空字符的长度。

你有时会看到const char*是因为通常的数组指针衰减。

但我不明白为什么它可以是const char*,因为以下行在VS12中被接受:char* s = "Hello";

这在C++03中是正确的行为(作为通常的const-correctness规则的例外),但自那以后已经被弃用。符合C++11标准的编译器不应该接受那段代码。


2
“通常的数组指针衰变”并不是在所有情况下都会发生。在 C 中,它只会发生在数组表达式不是一元 &sizeof 的操作数,或者是用于初始化数组(子)对象的初始化器中的字符串字面量时。C++ 有更多的例外情况。 - Keith Thompson
正确的术语是_Array-to-pointer Conversion_,它是最新C++标准第4条文档中记录的_Standard Conversion_。粗略地说,在某些上下文中编译器可以隐式地将标准转换应用于表达式。 - Andrew Tomazos

5
字符串字面值的类型是char const[N],其中N是包括终止空字符在内的字符数。虽然这种类型不能转换为char*,但C++标准包含一个条款,允许将字符串字面值分配给char*。添加此条款是为了支持兼容性,特别是对于没有const的C代码。
标准中与该类型相关的条款是2.14.5 [lex.string]第8段:

普通字符串字面值和UTF-8字符串字面值也称为窄字符串字面值。 窄字符串字面值具有类型“n个const char的数组”,其中n是如下所定义的字符串的大小,并且具有静态存储期(3.7)。


1
请注意,这个异常条款现在已经被弃用了,尝试将字符串字面值分配给 char* 应该会产生编译时错误。 - syam
@syam - "已弃用"意味着它仍然合法,但在未来可能会消失。在C++03中,将字符串文字转换为char*已被弃用;在C++11中,它变得无效。然而,语言定义不需要“编译时错误”。对于可诊断约束的违规行为,唯一的要求是编译器发出诊断;完成后,它可以自由地继续编译代码。这是实现特定扩展的钩子。只有一种情况需要编译器拒绝编译代码:#error指令。 - Pete Becker

-1

首先,C++字符串字面值的类型是由nconst char数组构成。其次,如果你想用字符串字面值初始化wchar_t,你需要编写以下代码:

wchar_t* s = L"hello"

这不是有效的代码,只是一个测试来查看给定的错误。标准确实让它听起来像应该是一个数组。 - Jesse Emond
7
不,字符串字面值不是 const char*,而是 const char[SIZE],正如其他答案所解释的那样。-1 - syam
1
然后解释为什么 sizeof "hello, world" 的结果是13。 - Keith Thompson
@Keith:在初始化字符串常量时,你会自动获得一个结尾的0。 - Jongware
1
@Jongware 我知道这一点。我正在要求Paul Evans解释为什么它与sizeof(const char*)不同。(是的,我也知道这一点。) - Keith Thompson
显示剩余2条评论

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