sizeof样式:sizeof(type)或sizeof变量?


22

我已经看到了两种sizeof用于与内存相关的操作的样式(例如in memsetmalloc):

  • sizeof(type)
  • sizeof variable 要么 sizeof(variable)

您希望使用哪种样式,还是将两种样式混合使用?何时使用每种样式?每种样式的优缺点是什么,以及何时使用它们?

作为示例,我可以看到以下两种情况,其中一种样式有帮助,而另一种则无济于事:

当您得到错误的指针间接指示时:

type *var;
...
memset(var, 0, sizeof var);    /* oops */

当类型更改时:

new_type var;    /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type));    /* oops */

Answers:


30

我perfer sizeof(variable)sizeof(type)。考虑:

int a1;
float a2;
memset(&a1,0,sizeof(a1));
memset(&a2,0,sizeof(a2));

int a1;
float a2;
memset(&a1,0,sizeof(int));
memset(&a2,0,sizeof(float));

在第一种情况下,很容易验证是否将正确的尺寸传递给memset。在第二种情况下,您需要不断检查顶部和底部,以确保您保持一致。


4
另外,如果更改变量的类型,则必须更改假定类型的代码。我认为最好对代码尽可能少地依赖类型。(我当时受到一个大型的16位到32位转换项目的影响。)

这对于处理不常创建typedef的C数组,但使用诸如char array [MAX_SIZE]之类的方法更可取。
mattnz

@ vy32:错误1: “ sizeof(array)不返回数组的大小...指向数组的指针的大小” -如果array确实是C数组,则sizeof(array)返回存储数组元素所需的字节数。如果array是指向衰变的C数组的第一个元素的指针,则您的语句成立。将C数组作为函数参数传递会使它看起来像函数中的指针-证明它是数组的所有信息(如数组大小)都会丢失。这就是为什么它腐烂了错误2: “数组在C语言中实际上并不存在; ...只是指针的语法糖。”
Johann Gerell 2014年

9

偏好(一如既往)是尽可能直接反映您的意图。

是否打算针对现有变量的内存进行操作?如果是这样,请使用sizeof(variable),因为它尽可能接近地表明您关心的是变量本身的内存。

是否打算对类型进行一些计算,例如确定应为新实例分配多少内存?如果是这样,请使用sizeof(type)

也就是说,我更喜欢

struct foo *bar;
bar = (struct foo *) malloc(sizeof(struct foo));

过度

bar = (struct foo *) malloc(sizeof(*bar));

因为后一种情况看起来像您正在尝试访问尚不存在的变量。

另一方面,我更喜欢

char Buffer[256];
memset(Buffer, 0, sizeof(Buffer));

过度

char Buffer[256];
memset(Buffer, 0, 256 * sizeof(char));

因为显然是为了使变量的内容零填充,所以这是我们应该操作的变量。在这里,尝试使用元数据类型只会使事情变得混乱。



我总是这样做,但这是个人喜好的问题。我认为void *会自动将强制转换为其他指针类型,这是不正确的。
艾丹·库利(Aidan Cully)

3

我会极大地喜欢sizeof(type)sizeof variable。即使它使您更加担心类型并进行更多更改,它仍可以帮助您避免指针间接错误,该错误是C语言中最常见的错误原因之一

我不会担心类型sizeof(type)更改的错误;每当更改变量的类型时,都应进行快速扫描以查看该变量的使用位置以及是否需要更改任何sizeof(type)语句。即使总是有可能出错,但与指针间接错误相比,它的风险要低得多。

的一个优点sizeof variable是用于数组,但是在实践中我发现将数组作为对的first / len进行传递更为常见(在这种情况下,仅使用长度),而且由于以下原因也很容易弄错大小:数组/指针衰减,如本例所示:

ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
  memcpy( mat, src, sizeof( src ) );    /* NOT the same as 3*3*sizeof(float) */
}

2
“快速扫描以查看在何处使用了该变量。...总是有可能出错。”对我来说,这是执行sizeof(type)的最大危险,这就是为什么我始终执行sizeof(variable)。因为这种危险的最终结果是一切仍然可能编译,即使您犯了一个错误,也可能要花费一年多的时间或随机崩溃并缓冲损坏,才可以发现它。而且我无法在该问题与“指针间接错误”之间建立联系(显然,每个问题的时间窗口约为30秒)。
DXM

@DXM使用sizeof操作数,如果它是一个值,则为sizeof var; 如果是指针,则为sizeof *var。这也是人们可能会犯错的事情,编译器会很乐意接受它而不会提出投诉。我认为这些错误比sizeof(type)形式上的错误更难发现,也更常见。
congusbongus 2013年

1
正确的选择-C类型和sizeof运算符从根本上被破坏了,永远不会可靠,程序员不能做任何事情来解决它。
mattnz

当帖子被标记时C,发布C代码比C ++代码更具信息性mat3_t::mat3_t(...)
chux-恢复莫妮卡

0

目的是消除冗余。如果将sizeof用于与变量相关的操作,那么显然应该在sizeof中反映出来。是的,您可以像第一个示例中那样弄糟,但是解决方法不是使用类型,而是使用* var,可以正确地匹配目标。

为了减轻此类问题,通常使用针对用例进行了培训的宏,模板和类似工具,而不是裸露的sizeof。

请参阅我的CLEAR宏,该专门用于代替裸内存集。在间接输入错误或结构内容获取向量或字符串的情况下,多次保存了我的屁股...


诸如此类的宏给C的宏编程起了不好的名字……
mattnz

@mattnz:请显示更好的选择。谈论抽象的东西要比创建实际工作的程序容易得多
Balog Pal 2013年

1
链接的宏是C ++,这篇文章被标记为“ C”(它们是不同的语言),艾达是我的建议。
mattnz

@mattnz:相同的主题显示了如何以类似的方式对C执行。您似乎完全忘记了要点,这不是实际的内容实现,而是与原始内容相比更安全的用法。顺便说一句,方式也可读。
2013年

0

业务逻辑定义您的选择。

  1. 如果您的代码引用了特定变量,而没有该变量,则您的代码毫无意义-选择 sizeof(var)

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


-1

取决于目的,sizeof(变量)可能是最佳解决方案。这样,您可以根据需要更改变量类型,而无需更正该类型的所有条目。但同样,这取决于您的目标。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.