【问题标题】:Is there anything wrong with `something_t* x = malloc(sizeof(*x))`?`something_t* x = malloc(sizeof(*x))` 有什么问题吗?
【发布时间】:2015-02-10 14:44:30
【问题描述】:

我正在用 C 语言编写一些极其重复的代码(读取 XML),我发现像这样编写代码可以更轻松地在构造函数中复制和粘贴代码*:

something_t* something_new(void)
{
    something_t* obj = malloc(sizeof(*obj));
    /* initialize */
    return obj;
}

我想知道的是,当我刚刚定义obj 时,像这样使用sizeof(*obj) 是安全的吗? GCC 没有显示任何警告并且代码运行良好,但 GCC 往往有“有用”的扩展,所以我不相信它。

* 是的,我意识到我应该只编写一个 Python 程序来编写我的 C 程序,但它几乎已经完成了。

【问题讨论】:

标签: c gcc malloc sizeof


【解决方案1】:
something_t* obj = malloc(sizeof(*obj));

我想知道的是,使用sizeof(*obj) 是安全的 像这样,当我刚刚定义obj?

您有一个声明,其中包括:

  • 类型说明符 something_t
  • 声明符 * obj
  • =
  • 初始化器 malloc(sizeof(*obj))
  • ;

C 标准在标识符范围部分中说:

结构、联合和枚举标记的范围仅开始于 在标记出现在声明的类型说明符中之后 标签。每个枚举常量的作用域都在 其定义枚举数在枚举数列表中的出现。任何其他 标识符的范围在其完成后开始 声明者。

由于obj 具有在其声明符完成后开始的范围,因此标准保证初始化程序中使用的标识符指的是刚刚定义的对象。

【讨论】:

    【解决方案2】:

    虽然我们是这样给出 sizeof 的。

    something_t* obj = malloc(sizeof(obj));
    

    它将内存分配给该指针变量作为四个字节(分配给指针变量的字节。)

    something_t* obj = malloc(sizeof(*obj));
    

    它将采用声明给该指针的数据类型。

    例如,

    char *p;
    printf("%d\n",sizeof(p));
    

    它将返回值为 4。

    printf("%d\n",sizeof(*p));
    

    现在它将返回值为 1。这是分配给字符的字节。因此,当我们在 sizeof 中使用 *p 时,它将采用数据类型。我不知道这是你期待的答案。

    【讨论】:

    • 是的,我的示例代码正在执行sizeof(*obj),而不是sizeof(obj),正是出于这个原因..
    • 我只是不认为你在回答我的问题。我已经知道我应该这样做sizeof(*obj)
    • @BrendanLong 好的,我很抱歉。但我不清楚你在期待什么!。
    【解决方案3】:

    很安全。例如,

    n = sizeof(*(int *)NULL);
    

    在这种情况下,不会发生 NULL 指针访问,因为编译器可以在运行时不知道 "*(int *)NULL" 的值的情况下计算操作数的大小。

    C89/90 标准保证 'sizeof' 表达式是一个常量;它在编译阶段被翻译成常量(例如0x04)并嵌入到二进制代码中。

    在 C99 标准中,'sizeof' 表达式并不总是编译时常量,因为引入了可变长度数组。例如,

    n = sizeof(int [*(int *)NULL]);
    

    在这种情况下,需要在运行时知道“*(int *)NULL”的值来计算“int[]”的大小。

    【讨论】:

    • 我们只讨论sizeof *variable_name的案例
    • 在 `sizeof *obj` 或 `sizeof *(T *)NULL` 的情况下,您知道,在 C89/90 标准中不会发生任何指针访问。在这方面,是否分配变量名或立即值并不重要。
    猜你喜欢
    • 2019-03-12
    • 2012-01-03
    • 2014-08-13
    • 2010-09-29
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多