你的原始代码是无效的。它至少包含两个约束违规:它为不存在的对象提供了初始化程序,并尝试将类型为int*
的对象用1
(类型为int
)进行初始化。编译器可以(也应该)简单地拒绝它。gcc在仅警告错误后编译您的代码时过于宽容。生成的代码具有未定义的行为。
const char *cptr = "Hello";
上述内容是有效的。"
Hello
" 是一个数组类型的表达式(具体来说是
char[6]
类型)。在大多数情况下,包括这个例子,在这样的表达式中,它会被隐式转换为指向数组第0个元素的指针。请注意,我添加了
const
,这样编译器至少会警告我如果我试图修改
cptr
指向的数据。
int *iptr = { 1, 2, 3, 4, 5 }; // invalid
这是无效的。你可能希望它与 cptr
的处理方式类似。问题在于,{ 1, 2, 3, 4, 5 }
不是一个表达式;它仅在初始化程序中有效。它可以是数组对象的有效初始化程序,但由于不是表达式,因此不适用数组到指针的转换规则。
假设您的编译器支持 C99 或更高版本(特别是 复合字面量 特性),您可以编写:
int *iptr = (int[]){ 1, 2, 3, 4, 5 };
(这不是一个类型转换;语法类似,但{ ... }
不是一个表达式。)
复合字面量是数组类型的表达式,具体来说是int[5]
,并应用了数组到指针的转换。
需要注意的是:字符串字面量创建了一个数组对象,并且该对象具有静态存储期,这意味着它存在于整个程序的执行过程中。如果复合字面量出现在任何函数之外,则创建具有静态存储期的对象;如果出现在函数内部,则创建具有自动存储期的对象,这意味着当你到达当前块的末尾时,它将停止存在。在这种情况下,它是在main
函数内定义的,因此不太可能出现问题。但这是需要注意的。例如,以下代码是安全的:
const char *new_string(void) {
const char *result = "hello";
return result;
}
但这不是:
int *new_array(void) {
int *result = (int[]){ 1, 2, 3, 4, 5 };
return result;
}
因为数组在离开函数时会停止存在。为了避免这种情况,您可以显式创建数组对象以使其静态化:
int *new_array(void) {
static const int arr[] = { 1, 2, 3, 4, 5 };
int *result = arr;
return result;
}
int *ptr = {1,2,3,4,5};
的意思是int *ptr = (int *)1;
,这没有任何意义。(这是GCC扩展,不符合标准C。)如果你想要一个数组,请使用int ptr[] = {1,2,3,4,5};
。 - HolyBlackCat