使用Malloc在C中定义结构

Bla*_*ary 7 c memory malloc structure

我之前问了一个关于使用malloc定义结构的问题.这是大多数人给出的答案:

struct retValue* st = malloc(sizeof(*st));
Run Code Online (Sandbox Code Playgroud)

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

谢谢你的帮助

int*_*jay 19

sizeof运营商实际上并没有评估它的操作-它只是着眼于它的类型.这是在编译时而不是运行时完成的.因此可以在分配变量之前安全地执行.

  • 不,这是相反的方式.`*st`表示"st指向的东西",因此编译器返回结构的大小,而不是指针的大小. (5认同)
  • @Blackbinary:关闭:`st`是一个指针,但`*st`是一个结构.所以它看着`*st`并说"哦,那是一个`struct retValue`!" 然后为retValue结构分配足够的内存.`*st`的实际内容无关紧要. (3认同)

Voi*_*ter 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));
Run Code Online (Sandbox Code Playgroud)

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

gcc -fdump-tree-cfg test.c
Run Code Online (Sandbox Code Playgroud)

编译器将生成文件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

}
Run Code Online (Sandbox Code Playgroud)

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

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