2008-12-17 78 views
20

最近看到有人赞扬另一位用户使用sizeof var而不是sizeof(type)。我一直认为这只是一种风格选择。有什么重要的区别?作为一个例子,用f和FF线被认为是比G和GG线更好:“C”sizeof与类型或变量

typedef struct _foo {} foo; 

foo *f = malloc(count * sizeof f); 
foo *g = malloc(sizeof(foo) * count); 

foo **ff = malloc(count * sizeof *ff); 
foo **gg = malloc(sizeof(foo*) * count); 

在我看来,第一套仅仅是一个风格问题。但是在第二对线中,额外的第二个*很容易被乘法混淆。

+3

您在第一个`malloc`行有错误 - 它应该是`sizeof * f`。一般模式是`somevar = malloc(count * sizeof * somevar)`。 – caf 2009-12-22 05:13:56

回答

45

如果变量的类型改变了,如果变量是参数而不是类型,sizeof将不需要改变。

关于@ icepack的评论:类型与变量名称的变化的可能性或可​​能性不是问题。想象一下,变量名用作sizeof的参数,然后再改变。在最好的情况下,重构重命名操作会改变所有事件并且不会引入错误。在最糟糕的情况下,sizeof的一个实例被遗漏,编译器会抱怨并且你修复它。如果类型更改完成,则sizeof语句不会出现错误。

现在想象这个类型是sizeof的参数。如果变量的类型发生了变化,除了检查以外,没有其他办法可以查找与该变量相关的所有sizeof。你可以搜索,但你会得到相同类型的sizeof的所有无关用途的点击。如果错过了一个,由于尺寸不匹配,您将会遇到运行时问题,这更加麻烦。

+1

对于数组变量,sizeof(array)会给你数组的实际大小。它可以用来计算元素sizeof(array)/ sizeof(element)的个数。请注意,它不适用于通过指针分配的内存。 – 2008-12-17 07:24:00

+2

不是一个合理的论点。以同样的方式可以声称,如果变量的名称被改变,如果类型是参数而不是变量,sizeof将不需要改变。更改的可能性取决于特定的设计(并且在大多数情况下都不会或应该改变) – SomeWittyUsername 2012-12-08 08:25:57

+0

这个答案似乎并不是一个“最终”的解决方案,牢记它不包括代码逻辑依赖于typedef的情况在一个特定的变量上。你可以在下面看到我的答案。 – Riga 2014-05-20 11:13:18

3

行f和ff肯定比g和gg差。 sizeof f是指针大小,因为f是一个点。为了使它们等价,你必须写sizeof *f(或者为了更好的可读性,sizeof(*f))。

6

除了史蒂夫说的,让我补充一点,sizeof不会评估它的操作数。所以你可以自由地做任何事情。不仅可以使用尚未初始化的变量,还可以取消引用空指针,调用未定义的函数,但只声明并执行任何其他类型的东西。我鼓励你总是使用表达式版本,因为史蒂夫很好地解释了这一点。

另外考虑到有时候typenames真的很长且不可读,只是想到指向函数的指针(特别是在C++中)。而不是写sizeof(my_long_type<weird, stuff>)你只是做sizeof t

+0

4年过去了,C++中的long类型名称问题已经被`decltype`减少了:) – SomeWittyUsername 2012-12-08 08:28:34

0

考虑变量的大小可能会有意想不到的结果。当变量是数组时,sizeof(array)将返回数组的大小,而不是单个元素的大小或指针的大小。取指针的大小将返回指针的大小。但是由于数组在传递时通常表示为指针,因此可能会引起混淆。

2

我倾向于在内存分配中使用sizeof(type),但在使用本地或全局变量时总是使用sizeof(variable)。尽管如此,建议中总是有智慧使用变量名称。

我也有过很长时间的讨论(相当于有时会动画,持续了几天 - 我们最终同意在这个问题上有所不同),关于是否可以使用sizeof(variable)或者它是否必须是sizeof variable;也就是说,括号是否包含sizeof的参数是否重要?我从来没有遇到过一个编译器,该编译器的威胁大约是sizeof(variable),所以我选择统一性,并始终使用sizeof的括号。我的同事同样坚持认为括号不能用于变量;无论如何,在带括号和不带括号的符号之间都存在着有价值的区别。我没有被说服 - 我不希望被说服。

在一个完全不同的策略,一个关于sizeof其他几个要点:

  • 如果您使用C99和VLA - 变长数组 - 然后sizeof(vla)是不是编译时间常数。谨防!
  • C预处理器不理解sizeof这是一个令人讨厌但逻辑。
4

您可能会看到这些差别不大:

foo **ff = malloc(count * sizeof *ff); 
foo **gg = malloc(sizeof(foo*) * count); 

..但如果什么配置是不是附近的声明?如果我遇到这样一行:

ff = realloc(ff, count * sizeof *ff); 

那么我有理由相信该行是正确的,甚至没有记住的ff类型。但是,如果我看到这一点:

ff = realloc(ff, count * sizeof(foo *)); 

那么我可能有点可疑,并需要查找的ff类型把我放心了。

0

业务逻辑定义您的选择。

  1. 如果你的代码是指一个特定的变量,如果没有这个变量的代码是没有意义的 - 选择sizeof(var)

  2. 如果你有一组特别的类型变量代码的交易 - 选择sizeof(type)。 如果你有一个typedef,通常你需要这个,它定义了许多你根据它们的类型处理不同的变量(例如序列化)。您可能不知道哪些变量将保留在将来的代码版本中,因此选择type作为参数在逻辑上是正确的。即使更改此类typedef也不会影响您的sizeof系列。