“C”sizeof与一个types或variables
最近看到有人赞扬另一位用户使用sizeof var而不是sizeof(type)。 我一直认为这只是一种风格的select。 有什么重大的区别? 举例来说,f和ff的行被认为比g和gg的行更好:
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);
在我看来,第一套只是一个风格问题。 但是在第二对线中,额外的第二个*很容易被混淆为乘法。
如果variables的types改变了,如果variables是参数,sizeof将不需要改变,而不是types。
关于@ icepack的评论:typesvariables名称variables的可能性或可能性不是问题。 想象一下,variables名被用作sizeof的参数,然后被改变。 在最好的情况下,重构重命名操作会改变所有的事件,并且不会引入错误。 在最糟糕的情况下,一个sizeof的实例被遗漏,编译器会抱怨并且你修复它。 如果types更改完成,那么在sizeof语句中不会出现错误。
现在想象这个types是sizeof的参数。 如果variables的types被改变,除了检查以外,没有办法find与该variables有关的所有sizeof。 你可以search,但是你会得到相同types的sizeof的所有不相关的用途。 如果错过了一个,那么由于尺寸不匹配,你将会遇到一个运行时问题,这是很麻烦的。
除了史蒂夫所说的,我还要补充一点,sizeof不会评估它的操作数。 所以你可以自由地做任何事情。 不仅可以使用尚未初始化的variables,而且还可以取消引用空指针,调用未定义的函数,但只声明并执行其他任何types的东西。 我鼓励你总是使用expression式版本,因为史蒂夫解释很大。
还要考虑到有时候typenames真的很长且不可读,只要想一下指向函数的指针(特别是在C ++中)。 而不是写sizeof(my_long_type<weird, stuff>)
你只是做sizeof t
。
你可能看不到这些之间的区别:
foo **ff = malloc(count * sizeof *ff); foo **gg = malloc(sizeof(foo*) * count);
..但如果分配不在临近声明怎么办? 如果我遇到像下面这样的一行:
ff = realloc(ff, count * sizeof *ff);
那么我有理由相信这条线是正确的,甚至没有记住ff
的types。 但是,如果我看到这个:
ff = realloc(ff, count * sizeof(foo *));
那么我可能会有点怀疑,并且需要查找ff
的types来让我放心。
f和ff行肯定比g和gg差。 sizeof f
是指针的大小,因为f是一个点。 为了使它们等价,你必须写sizeof *f
(或者为了更好的可读性, sizeof(*f)
)。
我倾向于在内存分配中使用sizeof(type)
,但在使用本地或全局variables时总是使用sizeof(variable)
。 不过,build议中总是有智慧使用variables名称。
我还有一个长时间的讨论(有时甚至是animation,而且持续了几天 – 我们最终同意在这个问题上有所不同):是否可以使用sizeof(variable)
还是一定是sizeof variable
; 也就是说,括号是否包含了sizeof
的参数是否重要? 我从来没有遇到过关于sizeof(variable)
的编译器,所以我select统一性,并总是使用sizeof
的括号。 我的同事同样坚持认为括号不能用于变数; 不pipe怎样,在有和没有括号的符号之间存在/有一个有价值的区别。 我没有被说服 – 我不希望被说服。
在完全不同的方面,还有一些关于sizeof
的其他观点:
- 如果您使用C99和VLA – 可变长度数组 – 那么
sizeof(vla)
不是编译时常量。 谨防! - C预处理器不了解
sizeof
哪个是令人讨厌但是合乎逻辑的。
考虑一个variables的大小可能会有意想不到的结果。 当variables是数组时,sizeof(array)将返回数组的大小,而不是单个元素的大小或指针的大小。 取指针的大小将返回指针的大小。 但是由于数组在传递时通常表示为指针,所以事情会变得混乱。
业务逻辑定义您的select。
-
如果你的代码引用了一个特定的variables而没有这个variables,你的代码就没有意义了 – select
sizeof(var)
-
如果您使用特定types的代码处理一组variables,请select
sizeof(type)
。 通常你需要这个,如果你有一个typedef
定义了许多你根据它们的types处理不同的variables(例如序列化)。 您可能不知道这些variables中的哪些将保留在将来的代码版本中,因此selecttype作为参数在逻辑上是正确的。 即使改变这种typedef
也不会影响你的sizeof
行。