使用Malloc在C中定义结构

时间:2010-02-01 16:58:08

标签: c memory malloc structure

我问question earlier使用malloc定义结构。 这是大多数人给出的答案:

struct retValue* st = malloc(sizeof(*st));

我向朋友展示了我的代码,我们遇到了绊脚石。 有人可以解释为什么这段代码有效吗? 从我的观点来看,当你对它进行malloc时没有定义* st,因此那里可能存在任何类型的垃圾。它应该是malloc(sizeof(struct retValue))

感谢您的帮助

4 个答案:

答案 0 :(得分:19)

sizeof运算符实际上并未计算其操作数 - 它只是查看其类型。这是在编译时而不是运行时完成的。因此,可以在分配变量之前安全地执行它。

答案 1 :(得分:19)

Sizeof查看赋予它的表达式的类型,它不会计算表达式。因此,您只需要确保声明表达式中使用的变量,以便编译器可以推断出它们的类型。

在您的示例中,st已经被声明为指向struct-ret-retValue的指针。因此,编译器能够推断出表达式“* st”的类型。

虽然看起来它已经在您的代码中声明,但编译器已经为您处理了它。代码中的所有声明都将移动到编译器出现的块的开头。假设你写了

说明编译器可用知识的一种方法是查看它生成的中间输出。考虑这个示例代码...

struct retValue {long int a, long int b};
...
printf("Hello World!\n");
struct retValue* st = malloc(sizeof(*st));

使用gcc作为示例,并在 test.c main()函数中使用上面的代码,让我们通过运行来查看中间输出...

gcc -fdump-tree-cfg test.c

编译器将生成文件 test.c.022t.cfg - 看看它,你会看到

[ ... removed internal stuff ...]
;; Function main (main)

Merging blocks 2 and 3
main (argc, argv)
{
  struct retValue * st;
  int D.3097;
  void * D.3096;

  # BLOCK 2
  # PRED: ENTRY (fallthru)
  __builtin_puts (&"Hello World!"[0]);
  D.3096 = malloc (16);
  st = (struct retValue *) D.3096;
  D.3097 = 0;
  return D.3097;
  # SUCC: EXIT

}

注意声明如何移动到块的开头,malloc的参数已经被实际值替换,表示表达式求值的类型的大小。正如评论中所指出的,声明被移到块顶部的事实是编译器的实现细节。但是,编译器能够执行此操作并将正确的大小插入malloc all这一事实表明编译器能够从输入中推断出必要的信息。

我个人更喜欢将实际的类型名称作为sizeof的参数,但这可能是编码风格的问题,我认为这种一致性胜过个人偏好。

答案 2 :(得分:1)

重要的是结构类型的声明/定义,而不是这类类的对象的定义。到达malloc时,编译器将遇到声明/定义,否则会遇到编译错误。

sizeof不评估其操作数的事实是一个副问题。

未成年人:当我们向sizeof提供类型名称时,请记住我们需要括号,如下所示:

sizeof(struct retValue);

而不是对象,我们只是这样做:

sizeof *st;

参见标准:

  

6.5.3一元运算符语法

unary-expression:
[...]
sizeof unary-expression
sizeof ( type-name )

答案 3 :(得分:0)

在C中,sizeof是一个运算符,不会计算其参数。这可能导致“有趣”的影响,C新手不一定会预料到。我在my answer中更详细地提到了“最奇怪的语言特征”问题。