在C语言中初始化整型指针

3

关于在C中初始化int指针的一个非常简单的问题。我被告知:

刚刚被告知

int *varname = {0};  

不是有效的。

我还没有找到明确指出这一点的参考资料,但我相信(基于评论者的声誉),它很可能是无效的,即使它可以编译、构建,并且可以从calloc/malloc语句中接受内存。

请有人能指出为什么上述表达式无效的具体原因吗?


3
你所接收到的信息是错误的。C语言标准明确允许这种形式的初始化:标量的初始化器应为单个表达式,可选地包括在大括号内。 - Jens Gustedt
如果你打算使用数组,这可能会很有用:https://dev59.com/unE85IYBdhLWcg3w1HKF - Jens Wirth
@ryyker,没关系,Grzegorz Szpetkowski先生已经给出了一个不错的答案。 - Jens Gustedt
你是否试图同时将varname定义为指针并创建一个对象让它指向,类似于char *ptr = "hello";?如果是这样,请参考我的答案。如果不是,请忽略我的回答。 - Keith Thompson
正确初始化指针的方法是 int *varname = NULL;。 - user3629249
显示剩余3条评论
3个回答

4
这是有效的,我们可以通过查看C99草案标准6.7.8初始化的第11段来证明:

标量的初始化器应该是一个单一的表达式,可选地用大括号括起来。[...]

所以:
int *varname = {0}; 

根据第6.3.2.3节的指针内容,将初始化varnamenull指针,因为0是一个null指针常量

值为0的整数常量表达式,或者将此类表达式强制转换为void*类型,被称为null指针常量。55)如果将null指针常量转换为指针类型,则生成的指针被称为null指针[...]

而我们也知道,根据第6.2.5节的类型,指针是标量类型:

算术类型和指针类型统称为标量类型[...]


3
正如Grzegorz Szpetkowski的回答所说,该语法:
int *varname = {0};

这个代码是正确的,只是它不做你认为它应该做的事情。它相当于

int *varname = 0;

这等同于

int *varname = NULL

(假设NULL是可见的)
如果我对你试图做的事情的猜测是错误的,那么本答案的其余部分就不适用。
根据评论看来,这似乎不是OP试图做的事情。不确定是否删除此答案;它可能是对其他问题的一个好答案。
您可以初始化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

@ryyker:“我的意图是将int *array初始化为0。”--只是为了明确,你的意思是要将array变成空指针,对吗?(在链接的答案中,初始化并不是必须的,因为该对象无条件地被分配了另一个值。顺便说一下,{0}是任何类型对象的有效初始化器。) - Keith Thompson

2

这是:

int *varname = {0};

这只是等同于:

int *varname = 0;

这是NULL宏的一个有效替代方法(可以使用0整数常量或将该常量强制转换为void *类型)。

N1570(C11草案),6.3.2.3/3:

一个整数常量表达式,其值为0,或者将这种表达式转换为类型void *,称为空指针常量。如果将一个空指针常量转换为指针类型,则所得到的指针,称为空指针,保证与任何对象或函数的指针均不相等。

示例(http://ideone.com/9917zk):

#include <stdio.h>

int main(void)
{
    int *varname = {0};

    printf("%p\n", (void *) varname);

    return 0;
}

它的输出仅仅是:
(nil)

(作为额外的注释,nil这个术语是由阿尔弗雷德·塔斯基发明的)


@antikbd 完全不是。什么数组?varname只是一个指针。 - Jonathon Reinhart
@antikbd:什么数组?声明创建了一个指针对象,而不是数组。初始化= {0}等同于= 0,也等同于= NULL - Keith Thompson
1
@antikbd:这只是 C 语法的一种怪异,不是真正的数组初始化器。 - Grzegorz Szpetkowski
哦,我明白了。我最近几周一直在大量使用指针编程,但仍然会对这些东西感到困惑! - antikbd
那么int *varname = {0}和int *varname = NULL之间根本没有任何区别?如果是这样的话,那么为什么{}大括号还被允许使用呢? - antikbd
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接