3

我多年来一直在使用它,即:

text = (char *)malloc( sizeof(char[1234]) );

代替:

text = (char *)malloc( sizeof(char) * 1234 );

人们告诉我这很危险,但没有人能说出原因。我检查了 C 规范,它是合法的。这里有什么陷阱吗?

4

5 回答 5

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

最后,这不是一个很常见的习语,所以阅读代码的人可能会一时感到困惑。

当然,这些陷阱是否值得努力改变你的习惯取决于你:)

于 2009-09-28T00:28:09.753 回答
4

我使用的成语是:

someptr = malloc(number_elems * sizeof *someptr);

对我来说,这样做的好处是如果我需要更改元素的类型,我不需要担心 malloc 调用。

int *data;
data = malloc(100 * sizeof *data);

...后来我意识到数据应该是unsigned long...

unsigned long *data;
data = malloc(100 * sizeof *data); /* no change from previous version */
于 2009-09-28T00:47:10.783 回答
3

我建议使用变量而不是类型:

text = malloc(sizeof(*text)*1234));

这样当您意识到支持 i18n 会很好,并将定义从:更改

char *text;

为:

wchar_t *text;

您仍然有足够的空间容纳 1234 个元素,而无需修改所有分配来切换它们从 'char' 到 'wchar_t' 来匹配。当然,这同样适用于其他类型——short 与 int 与 long、float 与 double 等。

于 2009-09-28T00:46:29.700 回答
3

这是合法的,并且按照您所说的方式进行操作是安全的:

text = (char *)malloc( sizeof(char[1234]) );

通常,尽管人们使用 sizeof 使用最小的最原始数据类型,但可以通过包括填充在内的计数。

您可能听说它不安全,因为有人认为数组可能在元素之间有填充。

但是数组元素之间永远不会有填充。C99 标准规定数组必须是内存的连续部分。

尽管在 C 中的结构中,您可以在数组之前或之后进行填充。

于 2009-09-28T00:33:39.943 回答
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
}
于 2009-09-29T08:12:21.437 回答