请考虑以下代码:
#include<stdio.h>
int main()
{
char *ptr={'R','E','D','\0'};
//char *ptr="RED";
}
它显示以下警告列表:
warning: initialization makes pointer from integer without a cast|
warning: excess elements in scalar initializer|
warning: (near initialization for 'ptr')|
但是,如果我注释掉第一个语句并激活第二个语句(在我的代码中注释掉),那么工作正常。
为什么会这样?为什么在第一种情况下没有指向同一数组的指针没有分配给ptr
,就像在第二种情况下那样?这有什么严格的技术原因?< / p>
答案 0 :(得分:4)
在6.7.9(11)[N1570草案中,与C99的6.7.8(11)相同],指明
标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后);与简单赋值相同的类型约束和转换适用,将标量的类型作为其声明类型的非限定版本。
在
中提供多个表达式char *ptr={'R','E','D','\0'};
你违反了“必须”的要求并调用未定义的行为(4(2)):
如果违反约束或运行时约束之外的''shall''或''shall not''要求,则行为未定义。
除此之外,这种特殊类型的未定义行为通常是主要的,因为编译器忽略了除第一个表达式之外的所有表达式 - 除了生成
warning: excess elements in scalar initializer|
并将代码视为
char *ptr = {'R'};
然后,毫不奇怪地导致了
warning: initialization makes pointer from integer without a cast|
因为'R'
是整数而不是指针。
另一方面,
char *ptr = "RED";
非常好,因为数组(1) "RED"
在初始化时被转换为指向其初始元素的指针,就像它将用于赋值一样。
(1)字符串文字是数组,而不是指针,如6.4.5(6)节所述:
在转换阶段7中,将值为零的字节或代码附加到由字符串文字或文字产生的每个多字节字符序列。 然后使用多字节字符序列初始化一个静态存储持续时间和长度的数组,该数组足以包含序列。对于字符串文字,数组元素的类型为char,并使用单个字节进行初始化多字节字符序列。对于UTF-8字符串文字,数组元素的类型为char,并使用UTF-8编码的多字节字符序列的字符进行初始化。
(宽字符串文字是wchar_t[N]
,char16_t[N]
或char32_t[N]
类型的数组,具体取决于它们是否以L
,u
或{{为前缀1}}。)