4

考虑以下代码:

#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,就像在第二种情况下一样?这是什么严格的技术原因?

4

1 回答 1

4

在 [N1570 草案的 6.7.9 (11) 中,与 C99 的 6.7.8 (11) 相同] 中规定

标量的初始值设定项应为单个表达式,可选择用大括号括起来。对象的初始值是表达式的初始值(转换后);应用与简单赋值相同的类型约束和转换,将标量的类型作为其声明类型的非限定版本。

通过在

char *ptr={'R','E','D','\0'};

您违反了“应”要求并调用了未定义的行为 (4 (2)):

如果违反了出现在约束或运行时约束之外的“应”或“不应”要求,则行为未定义。

顺便说一句,这种特殊类型的未定义行为通常主要表现为编译器忽略除第一个表达式之外的所有表达式 - 除了生成

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或. 为前缀U。)

于 2013-05-08T11:10:10.290 回答