我正在做一些C编码,在阅读了一些C代码后,我注意到有像
这样的代码片段char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
所以我想问一下为char数组分配内存的更多C-ish方法?使用sizeof(char)
并认为未来可以针对任何标准更改进行验证,或者省略它并直接使用该数字?
答案 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