我最近遇到了以下情况:
int ( *array )[10] = malloc(...);
根据我对C的语法和语法的理解,这看起来像废话。它看起来像正在创建(并初始化)一个数组,其中取消引用指针的值作为其标识符。
我理解指向数组的指针,并且通常至少使用malloc()在堆上分配它们。例如,这是有道理的:
int *array = malloc(sizeof (int*) * 10);
...但是,第一个例子看起来像不应该编译的乱码。显然,我错过了一些东西。
当我学习C时,我觉得我看到了这些,但谷歌搜索并没有帮助我理解。使用术语“指针”,“解除引用”和“初始化”进行搜索显然会使结果受到关于如何跟踪解除引用等信息的影响。我希望人类可以帮助我。
答案 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-expression
到malloc(...)
的中间步骤,因为他们只是让图表更难阅读。
答案 2 :(得分:5)
数组的地址和第一个元素的地址相等。
所以如果您有一个数组,例如
int array[10];
然后是指针p
和q
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 *
。