char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
我想问一下,分配char数组内存的更加C风格的方法是什么?是使用sizeof(char)
并且预防未来标准的改变,还是直接使用数字而忽略它?
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
我想问一下,分配char数组内存的更加C风格的方法是什么?是使用sizeof(char)
并且预防未来标准的改变,还是直接使用数字而忽略它?
更Cish的方式是
char* foo = malloc(someDynamicAmount * sizeof *foo);
引用变量而不是类型,这样就不需要类型。 并且不需要对malloc的结果进行强制类型转换(这很像C++)。
为了表明意图,我使用 sizeof(char)
。如果有人决定将 foo 设置为 int
,他知道他需要使用 sizeof(int)
才能使其继续正常工作。
或者省略它并使用数字
而且使用神奇数字不是很好的编程实践。
int *foo = malloc(sizeof(char) * some_quantity)
仍然可以编译通过而没有任何提示,从而悄悄地引入了一个错误。 - Blrflint
不是四个字节或char
不是八位时,这将会失败。标准允许两种情况,并且这两种情况都存在于现实世界中。如果您需要已知大小的整数,则<stdint.h>
提供了处理此类情况的类型。 - Blrfl我认为最佳实践是编写sizeof(*foo)
。这样,即使foo的类型发生更改,sizeof也不需要进行更正,你也不用担心。
比较:
float*baz = malloc(sizeof(float) * someDynamicAmount);
int *bar = malloc(sizeof(int) * someDynamicAmount);
char *foo = malloc(sizeof(char) * someDynamicAmount);
比较:
float*baz = malloc(sizeof(float) * someDynamicAmount);
int *bar = malloc(sizeof(int) * someDynamicAmount);
char *foo = malloc(someDynamicAmount);
我喜欢第一个版本。你更喜欢第二个吗?
long long
时,与其显示只添加了一行,你更希望看到增加了三行变化 -- 那么,写sizeof(char)
是可以接受的。;-p - Steve Jessopsizeof(char)
。在实践中,对于读取缓冲区,我会编写char *foo = malloc(BUF_SIZE);
,在那个几乎通用的代码中,我会编写char *foo = malloc(sizeof(*foo)*ARRAY_SIZE)
。我不会为了将前者视为与后者相同的“一般模式”的一部分而向我的代码添加我认为是噪音的内容。 - Steve Jessop您说得没错,从标准上来说,乘法是无关紧要的。但是有人养成了一种习惯,使得代码保持一致性。如果您始终使用sizeof()
,无论类型如何,就不会忘记。
char *foo = (char *)malloc(sizeof(char) * someDynamicAmount);
int *bar = (int *)malloc(sizeof(int) * someDynamicAmount);
T *p = malloc(N * sizeof *p);
或者
T *p;
...
p = malloc(N * sizeof *p);
sizeof
运算符》:sizeof char == 1
,而不是按照实现。因此,在为字符调用malloc()
和类似情况下省略sizeof(char)
是绝对正确的。在我看来,未来的C标准很可能不会允许实现特定大小的char
,因为太多的代码已经依赖于它为1,并且向后兼容性在C中非常重要。写 sizeof(char)
并不是为了使您的代码在标准发生可能更改时“未来可靠”。这通常表明您完全误解了 sizeof
的含义以及 C 语言中内存对象的整个基本模型,即所谓的“类型表示”。
sizeof
运算符之所以存在或有意义,唯一的原因是因为 C 指定对象在内存中具有“表示”,其最小单位为 unsigned char
。如果没有这个规定,存储将更加抽象,就没有使用 sizeof
和相关指针算术的必要了。
sizeof
定义为以 char
为“单位”,即 sizeof(T)==N
表示类型 T
占用 N
个 char
。鉴于此,sizeof(char)
是完全无意义的;它试图测量一个 char
占用多少个 char
。
char
的数量,而不是字节数。根据定义,sizeof(char)
为1
。 - Simon Richtersizeof
运算符返回其操作数的大小(以字节为单位),并且 当应用于类型为 char、unsigned char 或 signed char(或其限定版本)的操作数时,结果为 1
。我在这里看到它被定义为字节。 - Thomas Eding这完全是编码风格的问题。有几种不同的风格存在。
实际上回答这个问题,人们会写
malloc(n * sizeof(char))
malloc
的所有代码一致。下次他们可能需要int
,然后他们可以以完全相同的方式编写代码。malloc(n * sizeof(int))
因此,这样做的原因是为了保持编码风格的一致性。即使sizeof(char)
确实保证始终为1,因此是多余的。这是编写自我记录代码的一种方式。
然而,在C语言中使用malloc最常见的方式可能是
type* t = malloc(n * sizeof(*t));
或完全等价:
type* t = malloc(n * sizeof *t);
由于sizeof
运算符不会产生副作用,所以即使变量t
尚未初始化,此代码也是安全的。
type (*t)[n] = malloc( sizeof(type[n]) );
这可能是最正确的方法,就类型正确性而言。分配了数组的大小,然后我们用数组指针指向已分配的数组。
然而,这种风格的问题在于数组指针会增加语法上的额外复杂性:您必须将此数组解引用为(*t)[i]
,而不是t[i]
。这使得代码更难以阅读。(并且作为附注,如果n不是整数常量表达式,则该代码无法在旧的、过时的C编译器上编译。)
编码风格也可以写成:
char *foo = (char *)malloc(1 * someDynamicAmount);
但这样做是为了根据所需的基本数据类型数量增加动态分配内存。如果您想增加100个字符,它将增加100个字符。如果可能没有需要,但如果我们写101或102,那么这样做会浪费内存。根据基本数据类型进行操作不会浪费任何内存空间。
foo
的类型被更改,这样做会更好,因为它仍然会分配正确的内存量。在 memcpy 中执行此操作尤其重要。 - progrmrmalloc
的情况,你需要将返回值进行强制类型转换。我猜这是一个误导性的 C 习惯用法,可能还存在于 C++ 之前。有趣的是,对于 C 代码,有一份 CERT 建议说你应该始终将 malloc 的返回值进行强制类型转换,而另一份建议则表示不应该这样做。 - Steve Jessop*alloc
函数返回的是char *
而不是void *
,因此需要进行强制类型转换。这也是为什么这种做法很难被根除的一部分原因;老一辈的程序员可能出于习惯仍然这样做,当然任何看他们的代码或书籍的人都会效仿这种做法。我花了一段时间才意识到它已经不再必要,然后才停止这么做。 - John Bode