我已经使用它多年了,即:
text = (char *)malloc( sizeof(char[1234]) );
而不是:
text = (char *)malloc( sizeof(char) * 1234 );
人们告诉我这很危险,但没有人能说出原因。我检查了C规格,这是合法的。这里有陷阱吗?
答案 0 :(得分:7)
这可能是合法的,但有一些陷阱。
首先,如果您(或后来的维护者)盲目地用表达式替换类型,那么您将遇到问题:
sizeof(char *) * 4 => sizeof(x) * 4 // OK
sizeof(char *[4]) => sizeof(x[4]) // NOT OK
其次,并非所有编译器都支持可变长度数组:
sizeof(char *) * n // ALWAYS SUPPORTED
sizeof(char *[n]) // MAY NOT BE SUPPORTED
最后,这不是一个非常常见的习惯用法,因此阅读代码的人可能会暂时混淆。
这些陷阱是否值得努力改变你的习惯取决于你当然:)
答案 1 :(得分:4)
我使用的成语是:
someptr = malloc(number_elems * sizeof *someptr);
对我来说,这样做的好处是,如果我需要更改元素的类型,我不需要担心malloc调用。
int *data;
data = malloc(100 * sizeof *data);
...稍后我意识到数据应该是unsigned long
s ...
unsigned long *data;
data = malloc(100 * sizeof *data); /* no change from previous version */
答案 2 :(得分:3)
这是合法的,按你说的那样做是安全的:
text = (char *)malloc( sizeof(char[1234]) );
通常情况下,人们使用sizeof来处理最小的最原始数据类型,但过了包括计数中的填充。
你可能听说过它不安全,因为有人认为数组可能在元素之间有填充。
但是在数组的元素之间永远不会有填充。 C99标准规定数组必须是内存的连续部分。
您可以在数组之前或之后使用填充,但在C中的结构中。
答案 3 :(得分:3)
我建议使用变量而不是类型:
text = malloc(sizeof(*text)*1234));
这样,当你意识到支持i18n会很好,并改变定义时:
char *text;
于:
wchar_t *text;
你仍然有足够的空间容纳1234个元素,而不需要修改所有的分配来将它们从'char'切换到'wchar_t'来匹配。当然,这同样适用于其他类型 - 短对比与长对比,浮动与双对等等。
答案 4 :(得分:0)
两者之间存在实际差异。在第一个版本中,对象的数量需要是编译时常量。在第二个版本中,元素的数量可以在运行时确定。
所以,虽然两者都是
size_t x = sizeof(double[99]);
size_t y = sizeof(double)*99;
按预期工作,以下示例不会
void fun(int i) {
size_t x = sizeof(double[i]); // error, no compile-time constant
size_t y = sizeof(double) * i; // Fine
}