下面的代码中s2
的初始化有什么问题?
#include <stdio.h>
int main()
{
char *s1 = "foo";
char *s2 = {'f', 'o', 'o', '\0'};
printf("%c\n", s1[1]);
printf("%c\n", s2[1]);
return 0;
}
我想因为我可以按照上面的方式初始化s1
,s2
的初始化也可以正常工作。
但是这段代码会导致编译时警告以及运行时分段错误。
$ gcc foo.c
foo.c: In function ‘main’:
foo.c:6: warning: initialization makes pointer from integer without a cast
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
foo.c:6: warning: excess elements in scalar initializer
foo.c:6: warning: (near initialization for ‘s2’)
$ ./a.out
o
Segmentation fault (core dumped)
答案 0 :(得分:4)
是的,因为{'f', 'o', 'o', '\0'};
是大括号括起的初始化列表。它不能用于以任何方式初始化指针变量。但是,它可用于初始化char
数组,如
char s2[] = {'f', 'o', 'o', '\0'};
因为 数组不是指针 。
对于您的情况,您可以尝试使用compound literal作为解决方法。
像
这样的东西 char *s2 = (char []){'f', 'o', 'o', '\0'};
只是添加一些额外的信息,这些信息可能在阅读完这个答案后出现,就像为什么/如何用字符串文字初始化一个数组,比如
char s3[] = "Hello";
是可能的,因为如C11
中所述,章节§6.7.9,初始化
字符类型数组可以用字符串文字或UTF-8字符串初始化 文字,可选择括在括号中。字符串文字的连续字节(包括 如果有空间或数组的大小未知,则终止空字符)初始化 数组的元素。
答案 1 :(得分:4)
一个更好的问题是为什么你可以初始化一个带有字符串文字的指针,因为无法使用数组初始化程序初始化指针应该不足为奇:毕竟,数组不是指针。
然而,字符串文字是特殊的。 C允许您使用它们来初始化数组和指针,以便为创建以null结尾的字符串提供方便的语法。这就是为什么你的第一个语法适用于字符数组和字符指针。
答案 2 :(得分:1)
Designated initializers {}
初始化=
左侧的数据。例如
int a[6] = { 0, 0, 15, 0, 29, 0 };
初始化6个整数的数组,这就是初始化列表中每个元素都是整数的原因。
在你的
示例中char *s2 = {'f', 'o', 'o', '\0'};
因此,您将尝试使用整数值字符初始化指向char的指针,这不是您想要的。要初始化字符数组,您可以使用
char s2[] = {'f', 'o', 'o', '\0'};
语法或
char s2[] = "foo"; /* also allowed in C, as dasblinkenlight noted - the better
* question would be why this works and Sourav Ghosh gave
* the answer */