Sizeof 查看给定它的表达式的类型,它不会计算表达式。因此,您只需确保声明表达式中使用的变量,以便编译器可以推断出它们的类型。
在您的示例中, st 已声明为指向 struct-retValue 的指针。因此,编译器能够推断出表达式“*st”的类型。
尽管它看起来不像已经在您的代码中声明,但编译器已经为您处理好了。代码中的所有声明都会被编译器移至它们所在的块的开头。假设你写
说明编译器可用的知识的一种方法是查看它生成的中间输出。考虑这个示例代码...
struct retValue {long int a, long int b};
...
printf("Hello World!\n");
struct retValue* st = malloc(sizeof(*st));
以gcc为例,上面的代码在main()的函数test.c,让我们通过运行来查看中间输出...
gcc -fdump-tree-cfg test.c
编译器会生成文件测试.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 中,这一事实都表明编译器能够从输入中推断出必要的信息。
我个人更喜欢将实际类型名称作为 sizeof 的参数,但这可能是编码风格的问题,我认为一致性胜过个人偏好。