Geo*_*rge 451 c arrays pointers variable-declaration
以下声明之间有什么区别:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
Run Code Online (Sandbox Code Playgroud)
理解更复杂的声明的一般规则是什么?
Meh*_*ari 426
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
Run Code Online (Sandbox Code Playgroud)
第三个与第一个相同.
一般规则是运算符优先级.随着函数指针的出现,它可能变得更加复杂.
sig*_*ice 261
按照K&R的建议使用cdecl程序.
$ cdecl
Type `help' or `?' for help
cdecl> explain int* arr1[8];
declare arr1 as array 8 of pointer to int
cdecl> explain int (*arr2)[8]
declare arr2 as pointer to array 8 of int
cdecl> explain int *(arr3[8])
declare arr3 as array 8 of pointer to int
cdecl>
Run Code Online (Sandbox Code Playgroud)
它也是另一种方式.
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
Run Code Online (Sandbox Code Playgroud)
GMa*_*ckG 124
我不知道它是否有正式名称,但我称之为Right-Left Thingy(TM).
从变量开始,然后向右,向左,向右......等等.
int* arr1[8];
Run Code Online (Sandbox Code Playgroud)
arr1是一个包含8个整数指针的数组.
int (*arr2)[8];
Run Code Online (Sandbox Code Playgroud)
arr2是指向8个整数的数组的指针(括号内的左右).
int *(arr3[8]);
Run Code Online (Sandbox Code Playgroud)
arr3是一个由8个整数指针组成的数组.
这应该可以帮助您完成复杂的声明.
小智 25
int *a[4]; // Array of 4 pointers to int
int (*a)[4]; //a is a pointer to an integer array of size 4
int (*a[8])[5]; //a is an array of pointers to integer array of size 5
Run Code Online (Sandbox Code Playgroud)
小智 15
最后两个答案也可以从C中的黄金法则中扣除:
声明如下使用.
int (*arr2)[8];
如果你取消引用arr2会发生什么?你得到一个8个整数的数组.
int *(arr3[8]);
如果你从arr3中获取一个元素会怎么样?你得到一个指向整数的指针.
这在处理函数指针时也很有用.以sigjuice为例:
float *(*x)(void )
当你取消引用x时会发生什么?你得到一个你可以不带参数调用的函数.你打电话后会发生什么?它将返回一个指向float的指针.
但是,运算符优先级总是很棘手.但是,使用括号实际上也可能会造成混淆,因为声明随后使用.至少对我来说,直观地说,arr2看起来像是一个由8个指针组成的数组,但它实际上是另一种方式.只需要一些习惯.如果你问我:)总是足以为这些声明添加注释的原因:)
编辑:示例
顺便说一句,我偶然发现了以下情况:一个具有静态矩阵的函数,它使用指针算法来查看行指针是否超出范围.例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_ELEM(ar) (sizeof(ar) / sizeof((ar)[0]))
int *
put_off(const int newrow[2])
{
static int mymatrix[3][2];
static int (*rowp)[2] = mymatrix;
int (* const border)[] = mymatrix + NUM_ELEM(mymatrix);
memcpy(rowp, newrow, sizeof(*rowp));
rowp += 1;
if (rowp == border) {
rowp = mymatrix;
}
return *rowp;
}
int
main(int argc, char *argv[])
{
int i = 0;
int row[2] = {0, 1};
int *rout;
for (i = 0; i < 6; i++) {
row[0] = i;
row[1] += i;
rout = put_off(row);
printf("%d (%p): [%d, %d]\n", i, (void *) rout, rout[0], rout[1]);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
0 (0x804a02c): [0, 0] 1 (0x804a034): [0, 0] 2 (0x804a024): [0, 1] 3 (0x804a02c): [1, 2] 4 (0x804a034): [2, 4] 5 (0x804a024): [3, 7]
请注意,border的值永远不会改变,因此编译器可以对其进行优化.这与您最初可能要使用的内容不同const int (*border)[3]::它将border声明为指向3个整数数组的指针,只要该变量存在,该数组就不会更改值.但是,该指针可以在任何时候指向任何其他这样的数组.我们想要参数的那种行为(因为这个函数不会改变任何整数).声明如下使用.
(ps:随意改进这个样本!)
小智 5
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
Run Code Online (Sandbox Code Playgroud)