为什么`int(* array)[10] = malloc(...);`有效的C代码?

时间:2016-05-27 13:02:32

标签: c arrays pointers syntax malloc

我最近遇到了以下情况:

int ( *array )[10] = malloc(...);

根据我对C的语法和语法的理解,这看起来像废话。它看起来像正在创建(并初始化)一个数组,其中取消引用指针的值作为其标识符。

我理解指向数组的指针,并且通常至少使用malloc()在堆上分配它们。例如,这是有道理的:

int *array = malloc(sizeof (int*) * 10);

...但是,第一个例子看起来像不应该编译的乱码。显然,我错过了一些东西。

当我学习C时,我觉得我看到了这些,但谷歌搜索并没有帮助我理解。使用术语“指针”,“解除引用”和“初始化”进行搜索显然会使结果受到关于如何跟踪解除引用等信息的影响。我希望人类可以帮助我。

3 个答案:

答案 0 :(得分:11)

这是完全合法的 - 您正在分配一个指向十个整数数组的指针。

...中完成malloc的好方法是,如果只需要一个数组 * ,则使用sizeof(*array)

int ( *array )[10] = malloc(sizeof(*array));
  

例如,这是有道理的:int *array = malloc(sizeof (int*) * 10);

这是一个int的数组。第一种语法允许您创建int s的数组数组 - 例如

int ( *array )[10] = malloc(50*sizeof(*array));

给你一个50×10阵列。

* 这是good explanation of why sizeof(*array) is a good way of sizing your allocation

答案 1 :(得分:7)

int ( *array )[10] = malloc(...);

array声明为指向int的10元素数组的指针;使用malloc调用的结果初始化指针。它和写作一样

int (*array)[10] = NULL;
array = malloc( ... );

请记住

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

将分配足够的存储空间来保存N的{​​{1}}个实例,并将结果指针值分配给T。对于任何类型p 都是如此。

如果我们将T替换为T这样的数组类型,我们就会得到

R [10]

语义完全相同,所有改变的都是R (*p)[10] = malloc( sizeof *p * N ); 的类型;我们正在分配足够的存储空间来保存p N个实例。

  

根据我对C&C语法和语法的理解,这看起来像废话。

然后你需要重新审视这种理解。 C声明语法是 lot 比大多数人想象的更复杂。见online C 2011 standard的第6.7节。

修改

以下是语法分解的方法:

R [10]

我省略了从int ( * array )[ 10 ] = malloc( ... ); ^ ^ ^ ^ ^^ ^ ^ ^ ^ | | | | || | | | | | | pointer direct || | | | assignment | | | declarator || | | | expression | | | | || | | | | | | +-----+-----+ || | | | | | | | || | | | | | | declarator || | | | | | | | || | | | | | +---------+------------+| | | | | | | | | | | | | direct | assignment | | | | declarator | expression | | | | | | | | | | | +-------------+-----+------+ | | | | | | | direct | | | declarator | | type | | | specifier declarator | initializer | | | | | +---------------+-+ | | | init-declarator declaration | specifiers init-declarator-list | | +----------------------+------------------------+ | declaration 10以及从assignment-expressionmalloc(...)的中间步骤,因为他们只是让图表更难阅读。

答案 2 :(得分:5)

数组的地址和第一个元素的地址相等。

所以如果您有一个数组,例如

int array[10];

然后是指针pq

的值
int *p = array;

int ( *q )[10] = &array;

虽然指针的类型不同,但它们是相同的。

这些值等于数组的第一个元素的地址。在第一种情况下,元素的类型是int,而在第二种情况下,元素的类型是int[10]但在这两种情况下,它是未分配的已分配内存范围的地址取决于它在C中的解释方式。

您可以通过以下方式从指针p获取指针q

p = *q;

考虑到函数malloc返回一个指向void void *的指针,该指针在C中可以隐式转换为任何其他类型的指针。

因此这些陈述

int ( *array )[10] = malloc( 10 * sizeof( int ) );

int *array = malloc( 10 * sizeof( int ) );

在C中有效。

另一方面,函数free再次使用类型为void *的指针作为其参数。并且可以将其他类型的指针隐式转换为类型void *