【问题标题】:Initialization of int pointer in C在 C 中初始化 int 指针
【发布时间】:2014-11-12 20:41:56
【问题描述】:

关于在 C 中初始化 int 指针的一个非常简单的问题。我是 just informed

int *varname = {0};  

无效。

我还没有找到指出这一点的明确参考,但有信心(基于评论者代表)它可能是无效的,即使它编译、构建和接受来自 calloc/malloc 语句的内存也可以.

有人可以指出上述表达式无效的具体原因吗?

【问题讨论】:

  • @molbdnilo - 好的,但是类似于 duff's device 的语句是无效的,因为它不是 C 语法的一部分?.它是一种混合体,通过某种巧合碰巧提供了一种做某事的方法,标准中没有明确指出。这不相似吗?
  • 你被误导了。 C 标准明确允许这种形式的初始化:标量的初始化器应该是单个表达式,可选地用大括号括起来。
  • 如果您打算使用数组,这可能很有用:stackoverflow.com/questions/2589749/initialize-array-to-0-in-c
  • @ryyker,没关系,Grzegorz Szpetkowski 首先给出了一个不错的答案。
  • 您是否尝试同时将varname 定义为指针并为其创建一个指向的对象,类似于char *ptr = "hello";?如果是这样,请参阅我的答案。如果不是,那我的回答就完全不合时宜了。

标签: c pointers initialization


【解决方案1】:

这是有效的,我们可以通过转到 C99 draft standard 部分 6.7.8 Initialization 段落 11 看到这一点:

标量的初始值设定项应该是一个表达式,可选地用大括号括起来。 [...]

所以:

int *varname = {0}; 

varname初始化为一个空指针,因为0是一个空指针常量,根据6.3.2.3部分指针

值为 0 的整数常量表达式,或者这样的表达式 强制转换为 void * 类型,称为空指针常量。55) 如果为空 指针常量转换为指针类型,结果 指针,称为空指针 [...]

为了完整起见,我们知道指针是基于 6.2.5 部分的标量类型类型

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

【讨论】:

    【解决方案2】:

    int *varname = {0};
    

    就相当于:

    int *varname = 0;
    

    它是NULL 类对象宏的有效替换之一(作为0 整数常量或转换为void * 类型的常量)。

    N1570(C11 草案),6.3.2.3/3:

    值为 0 的整数常量表达式,或者这样的表达式 转换为 void * 类型,称为 空指针常量 如果为空 指针常量转换为指针类型,结果 指针,称为 null 指针,保证比较不等于 指向任何对象或函数的指针。

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

    #include <stdio.h>
    
    int main(void)
    {
        int *varname = {0};
    
        printf("%p\n", (void *) varname);
    
        return 0;
    }
    

    它的输出只是:

    (nil)
    

    (作为额外的部分,请注意 nil 术语是由 Alfred Tarski 发明的)

    【讨论】:

    • 如果我错了,请纠正我,但这里发生的情况是,由于尚未定义数组的边界,因此设置 int *varname = {0} 仅初始化第一个元素数组,对吧?
    • @antikbd 一点也不。什么阵法? varname 只是一个指针。
    • @antikbd:什么数组?该声明创建一个指针对象,而不是一个数组。初始化= {0}相当于= 0,相当于= NULL
    • @antikbd:这只是 C 语法的怪异,而不是真正的数组初始值设定项。
    • 哦,我明白了。在过去的几周里,我一直在大量使用指针进行编程,但仍然对这些东西感到困惑!
    【解决方案3】:

    正如 Grzegorz Szpetkowski 的回答所说,该语法:

    int *varname = {0};
    

    有效。它只是没有做我怀疑你认为它应该做的事情。相当于

    int *varname = 0;
    

    相当于

    int *varname = NULL
    

    (假设NULL 可见)。

    如果我对您尝试做的事情的猜测是错误的,则此答案的其余部分不适用。


    根据 cmets,看起来这不是 OP 想要做的。不确定是否删除此答案;这可能是其他问题的一个很好的答案。


    你可以初始化一个char*指针指向一个字符串字面量:

    char *cptr = "hello";
    

    字符串字面量"hello" 隐式创建了一个具有静态存储时长的匿名数组对象;初始化导致cptr 指向该数组的初始元素。

    在 C99 之前,没有等效的语法来定义非字符指针并同时为其创建指向的东西。

    C99 添加了复合文字。例如,这个:

    (int){42}
    

    创建一个值为42int 对象。与文字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} 是任何类型对象的有效初始化器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    • 2011-04-10
    • 2012-12-19
    • 1970-01-01
    • 2012-05-24
    • 2023-03-14
    • 1970-01-01
    相关资源
    最近更新 更多