关于在C中初始化int指针的一个非常简单的问题。我被告知:
int *varname = {0};
不是有效的。
我还没有找到明确指出这一点的参考资料,但我相信(基于评论者的声誉),它很可能是无效的,即使它可以编译、构建,并且可以从calloc/malloc语句中接受内存。
请有人能指出为什么上述表达式无效的具体原因吗?
关于在C中初始化int指针的一个非常简单的问题。我被告知:
int *varname = {0};
不是有效的。
我还没有找到明确指出这一点的参考资料,但我相信(基于评论者的声誉),它很可能是无效的,即使它可以编译、构建,并且可以从calloc/malloc语句中接受内存。
请有人能指出为什么上述表达式无效的具体原因吗?
6.7.8
节初始化的第11
段来证明:
所以:标量的初始化器应该是一个单一的表达式,可选地用大括号括起来。[...]
int *varname = {0};
根据第6.3.2.3
节的指针内容,将初始化varname
为null指针,因为0
是一个null指针常量:
值为0的整数常量表达式,或者将此类表达式强制转换为void*类型,被称为null指针常量。55)如果将null指针常量转换为指针类型,则生成的指针被称为null指针[...]
而我们也知道,根据第6.2.5
节的类型,指针是标量类型:
算术类型和指针类型统称为标量类型[...]
int *varname = {0};
这个代码是正确的,只是它不做你认为它应该做的事情。它相当于
int *varname = 0;
这等同于
int *varname = NULL
NULL
是可见的)char*
指针以指向字符串文字:char *cptr = "hello";
字符串字面量"hello"
隐式地创建了一个具有静态存储期的匿名数组对象;初始化使得cptr
指向该数组的初始元素。
在C99之前,没有定义非字符指针并同时创建它所指向内容的等价语法。
C99添加了复合字面量。例如:
(int){42}
使用int
关键字创建值为42
的对象。与字面量42
不同,这实际上是创建了一个对象,而不仅仅是一个值 - 这意味着它有一个地址。因此,以下代码:
int *iptr = &((int){42});
创建一个初始值为 42 的匿名 int
对象,并将 iptr
初始化为指向该对象的指针。(如果编译器支持复合字面量。)
复合字面量通常用于数组和结构类型,但对标量类型也有效。
需要注意的是:由字符串字面量创建的数组始终具有静态存储期,这意味着它存在于程序执行的整个过程中。由复合字面量创建的匿名对象的存储期取决于它出现的位置。如果它在函数内部,则对象具有自动存储期,这意味着它一旦离开最近的封闭块,就会停止存在。
所以给定:
char *cptr = "hello";
你可以安全地从函数中返回cptr
的值,并且它仍然有效。但是,考虑以下情况:
int *iptr = &((int){42});
从函数返回iptr
的值是很危险的,因为它所指向的对象将在调用者获得指针值之前停止存在。
做这种事情的一种更简单的方法是自己定义对象:
int obj = 42;
int *iptr = &obj;
obj
定义为static
。int *array
初始化为0
。”--只是为了明确,你的意思是要将array
变成空指针,对吗?(在链接的答案中,初始化并不是必须的,因为该对象无条件地被分配了另一个值。顺便说一下,{0}
是任何类型对象的有效初始化器。) - Keith Thompson这是:
int *varname = {0};
这只是等同于:
int *varname = 0;
这是NULL
宏的一个有效替代方法(可以使用0整数常量或将该常量强制转换为void *
类型)。
N1570(C11草案),6.3.2.3/3:
一个整数常量表达式,其值为0,或者将这种表达式转换为类型
void *
,称为空指针常量。如果将一个空指针常量转换为指针类型,则所得到的指针,称为空指针,保证与任何对象或函数的指针均不相等。
#include <stdio.h>
int main(void)
{
int *varname = {0};
printf("%p\n", (void *) varname);
return 0;
}
(nil)
(作为额外的注释,nil
这个术语是由阿尔弗雷德·塔斯基发明的)
varname
只是一个指针。 - Jonathon Reinhart= {0}
等同于= 0
,也等同于= NULL
。 - Keith Thompson
varname
定义为指针并创建一个对象让它指向,类似于char *ptr = "hello";
?如果是这样,请参考我的答案。如果不是,请忽略我的回答。 - Keith Thompson