char *s = "Hello"
char s[6] = "Hello"
上述任何一种语法都可以正常工作。
但是关注呢?
int a[3] = {1,2,3}
(这会很棒)int *a = {1, 2, 3};
?解释以及案例[2]和[4]之间的比较将有所帮助。
答案 0 :(得分:5)
这是因为"Hello"
被替换为“字符串文字的地址 Hello ”。
所以char *s = "Hello"
表示“为指针s
指定字符串文字 Hello ”的地址。
同时{1, 2, 3}
不构成地址且未被替换。除了地址之外,您不能为指针分配任何其他内容,因此您无法编写int *a = {1, 2, 3}
。
答案 1 :(得分:5)
无法工作的原因是未定义初始值的数据类型。对于字符串文字,这是由语法隐式给出的。但{ 1,2,3}
可以是数组,结构或许多其他变体。
您必须指定类型:
int *ia = (int []){1,2,3};
这使用复合文字(C99)。
请注意,这不仅适用于初始化,也适用于普通代码。
答案 2 :(得分:3)
char *s="Hello"
此处,s
是指向char
的指针,指向字符串文字"Hello"
的基地址。
char s[6]="Hello"
此处s
是一个包含char
,H
,e
,{{1}的6 l
个数组 }},l
和o
作为启动器值。
\0
此处,int a[3]={1,2,3}
是包含3个元素的a
数组,使用值int
,1
和2
初始化。
注意:以上三者都是合法和有效。
3
;无效。
此处,int *a={1,2,3}
的类型为a
,而大括号列表的值不会为int *
。因此,这不是已定义的行为且无效。
答案 3 :(得分:3)
案例4不受支持但其他案例受支持的原因是历史性的。这些因素是一些早期有影响力的程序员和编译器供应商之间的游说和政治相互作用,而非经过深思熟虑的技术决策。
所以,如果你正在寻找一个强有力的技术理由,你将找不到一个。
从历史上看,案例2和案例3在C演变的早期就得到了支持。你的案例2与
的效果相同。 char s[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
没有字符串文字的对应物来初始化除char
类型之外的任何数组。
历史上,案例1是希望实现
效果的程序员引入的异常 char s_temp[] = "Hello";
char *s = temp_s;
键入较少(即作为单个语句)。对案例1的支持的游说最终胜出(它被引入主流编译器,后来进入标准)。情况1是标准中唯一可以使用数组初始化器直接初始化指针而无需进行类型转换的情况。
从历史上看,案例4中的程序员从未有过要求或游说。
不管你喜欢与否,是支持案例1,2,3但案例4不支持的原因。
案例2和案例4之间没有真正的比较,因为它们(寻求)实现不同的事物。字符串文字(如案例2)是一个数组初始化程序,仅适用于char
的数组 - 没有非char
类型的对应项。情况4尝试使用数组初始化器初始化指针。
答案 4 :(得分:2)
int *a = {1, 2, 3};
在语法上是incorect,因为{1, 2, 3}
不能用于初始化指针。
然而,稍加修改就可以使其发挥作用:
int *a = (int []){1, 2, 3};
这是一个C99复合文字。
答案 5 :(得分:1)
使用字符串初始化字符数组是一种特殊情况:char s[6] = "hello"
被视为代码编写为char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0'};
。使用字符串初始化字符数组很常见,因此这个习惯用语很有意义。
答案 6 :(得分:0)
- 醇>
int a[3] = {1,2,3};
这是数组的正常初始化语法。
- 醇>
char s[6] = "Hello";
这是一个特殊情况初始化语法,仅适用于字符数组,您可以在右侧编写字符串文字,它将扩展为上面的常规初始化语法,即{{1 }}
- 醇>
char s[6] = {'H','e','l','l','o','\0'};
这是标量变量的常规初始化语法,初始化为右侧的表达式。这里,char *s = "Hello";
是一个有效的C表达式。
- 醇>
"Hello"
这与上述(1)的不同之处在于int *a = {1, 2, 3};
不是有效的C表达式。