如果标准符号为1,为什么要写`sizeof(char)`

时间:2011-08-30 13:23:55

标签: c coding-style

我正在做一些C编码,在阅读了一些C代码后,我注意到有像

这样的代码片段
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);

所以我想问一下为char数组分配内存的更多C-ish方法?使用sizeof(char)并认为未来可以针对任何标准更改进行验证,或者省略它并直接使用该数字?

12 个答案:

答案 0 :(得分:65)

更多Cish方式

char* foo = malloc(someDynamicAmount * sizeof *foo);

引用变量而不是类型,以便不需要类型。 并且没有转换malloc的结果(这是C ++ ish)。

答案 1 :(得分:29)

我做sizeof(char)以明确意图。如果有人决定他希望foo成为int他知道他需要sizeof(int)才能继续工作。

  
    

或省略它并使用数字

  

另外,使用幻数不是很好的编码习惯。

答案 2 :(得分:25)

恕我直言最佳做法是写sizeof(*foo)。那你就是  如果foo的类型发生变化且sizeof未得到纠正,也会被覆盖。

答案 3 :(得分:11)

比较

float*baz = malloc(sizeof(float) * someDynamicAmount);
int  *bar = malloc(sizeof(int)   * someDynamicAmount);
char *foo = malloc(sizeof(char)  * someDynamicAmount);

Vs的:

float*baz = malloc(sizeof(float) * someDynamicAmount);
int  *bar = malloc(sizeof(int)   * someDynamicAmount);
char *foo = malloc(someDynamicAmount);

我喜欢第一个版本。你更喜欢第二个吗?

答案 4 :(得分:7)

你是正确的,按照标准,乘法是不可靠的。也就是说,这看起来像是一个人变得一致的习惯。如果您总是使用sizeof(),无论其类型如何,您都不会忘记。

char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int  *bar = (int  *)malloc(sizeof(int)  * someDynamicAmount);

答案 5 :(得分:7)

常见的习语是

T *p = malloc(N * sizeof *p);

T *p;
...
p = malloc(N * sizeof *p);

这样您就不必担心类型了。

答案 6 :(得分:2)

引用C99 standard,第6.5.3.4节 sizeof运算符

  

应用于类型为 char,unsigned char或signed char 的操作数时   (或其合格版本)结果为1 。应用于具有数组的操作数时   type,结果是数组中的总字节数。应用于操作数时   具有结构或联合类型,结果是这样一个对象的总字节数,   包括内部和尾部填充。

即标准sizeof char == 1,而不是实施。因此,在为字符和类似情况调用sizeof(char)时省略malloc()是完全正确的。恕我直言,未来的C标准将允许char的特定于实现的大小,这是非常不可能的,因为过多的代码已经依赖于它为1,向后兼容性在C中非常重要。

因此,问题只是关于风格,而不是正确性,我支持AProgrammer's answer

答案 7 :(得分:1)

编写sizeof(char)并非“面向未来”,而是针对标准中可能发生的变化。这通常是对sizeof的含义以及C中内存对象的整个基本模型的完全误解的标志 - 在C标准的语言中被称为类型表示。 <{1}}运算符甚至存在或有意义的唯一原因是因为C指定对象在内存中以sizeof的最小可能单位表示“表示”。如果不是这样,存储将更加抽象,并且不会使用unsigned char和相关的指针算法。

sizeof sizeof的单位中定义,即char表示类型sizeof(T)==N占据T N秒。鉴于此,char完全是愚蠢的;它试图衡量sizeof(char)char的次数。

答案 8 :(得分:0)

这完全是编码风格的问题。有几种风格。

要真正回答这个问题,人们会写

malloc(n * sizeof(char))

保持所有使用malloc的代码保持一致。下次他们可能需要int然后他们可以用同样的方式编写代码,

malloc(n * sizeof(int))

所以为什么要保持编码风格一致。即使sizeof(char)确实保证总是为1,因此也是多余的。这是一种编写自我记录代码的方法。

但是,在C中使用malloc的最常用方法可能是

type* t = malloc(n * sizeof(*t));

或100%当量:

type* t = malloc(n * sizeof *t);

由于sizeof的运算符未评估副作用,因此即使变量t尚未初始化,此代码也是安全的。

第三种可能的风格是迂腐正确的风格,它将使用数组指针,因为我们分配的实际上是数组:

type (*t)[n] = malloc( sizeof(type[n]) );

就类型正确性而言,这可能是最正确的方法。分配了一个数组的大小,我们指向带有数组指针的已分配数组。

然而,这种风格的问题是数组指针增加了语法的额外复杂性:您必须将此数组取消引用为(*t)[i]而不是t[i]。它使代码更难阅读。 (另外作为旁注,如果n不是整数常量表达式,代码将无法在旧的,过时的C编译器上编译。)

答案 9 :(得分:-2)

编码风格也可以写成: -

char *foo = (char *)malloc(1 * someDynamicAmount);

但这样做是为了根据所需的基本数据类型的数量增加动态分配内存。如果你想增加100个字符,它将增加100个字符。如果可能没有必要,但如果我们写101或102这样做会浪费内存。根据基本数据类型执行它不会浪费任何内存空间

答案 10 :(得分:-2)

  

该标准故意模糊常见类型的大小。 [Wikipedia]

虽然char的大小不太可能不会改变,但short 的大小已经改变了。惯用的方式是:

type_t *foo = malloc(sizeof(type_t) * someDynamicAmount);

适用于任何类型(常见或复杂)type_t或

type_t *foo = malloc(sizeof(*foo) * someDynamicAmount);

这样你就可以决定稍后改变foo的类型,只在一个地方改变它。

答案 11 :(得分:-7)

考虑unicode和多字节字符串。如果char表示字符串中的单个字符,则它实际上可以占用多个字节,从而导致sizeof()&gt; 1