以下声明之间有什么区别:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
理解更复杂的声明的一般规则是什么?
以下声明之间有什么区别:
int* arr1[8];
int (*arr2)[8];
int *(arr3[8]);
理解更复杂的声明的一般规则是什么?
int* arr[8]; // An array of int pointers.
int (*arr)[8]; // A pointer to an array of integers
第三个与第一个相同。
一般规则是运算符优先级。当函数指针出现时,它可能会变得更加复杂。
( ) [ ]
从左到右结合,并且比*
具有更高的优先级,因此将int* arr[8]
读作大小为8的数组,其中每个元素指向一个整数,而int (*arr)[8]
则表示指向包含整数的大小为8的数组的指针。 - Mushy使用 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>
它也可以反过来使用。
cdecl> declare x as pointer to function(void) returning pointer to float
float *(*x)(void )
我不知道它是否有官方名称,但我称之为Right-Left Thingy(TM)。
从变量开始,向右走,然后向左,再向右......如此循环。
int* arr1[8];
arr1
是包含 8 个指向整数的指针的数组。
int (*arr2)[8];
arr2
是一个指向包含8个整数的数组的指针。(圆括号限制了从右到左的优先级。)
int *(arr3[8]);
arr3
是一个包含8个指向整数的指针的数组。
这可以帮助您处理复杂的声明。
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
[5]
)代表内部维度。这意味着(*a[8])
是第一维,因此是数组的外部表示。a
中每个元素所指向的是大小为5的不同整数数组。 - zeboidlund#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;
}
输出:
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个整数的数组的指针,只要该变量存在,其值将不会更改。但是,该指针可以随时指向任何其他这样的数组。我们希望实现的是参数的这种行为(因为此函数不会更改这些整数中的任何一个)。声明在使用之后。
(附言:请随意改善此示例!)
typedef int (*PointerToIntArray)[];
typedef int *ArrayOfIntPointers[];
[]
,()
等)比左一元运算符优先级高。所以,int *(*ptr)()[];
将是一个指向返回指向int的指针数组的函数的指针(尽快使用右操作符,因为你一旦离开括号就获取到它们)。error: ‘foo’ declared as function returning an array int foo(int arr_2[5][5])[5];
在GCC 8下使用 $ gcc -std=c11 -pedantic-errors test.c
。 - alx - recommends codidactint *(*ptr)();
允许稍后使用类似 p()[3]
(或 (*p)()[3]
)的表达式。 - Luis Coloradoint *foo(int arr_2[5][5]) { return &(arr_2[2][0]); }
并像这样调用:foo(arr)[4];
,这应该包含 arr[2][4]
,对吗? - alx - recommends codidact这是我的理解:
int *something[n];
[]
)的优先级高于解引用操作符(*
)。
因此,在此处我们将先应用[]
,然后再应用*
,使该语句等价于:int *(something[i]);
int num
表示num
是一个int
,int *ptr
或 int (*ptr)
表示ptr
的值为一个int
,这使得ptr
成为指向int
的指针。
这可以理解为,(某个东西中第i个索引的值)是一个整数。因此,(某个东西中第i个索引的值)是一个(整数指针),这使得该东西成为整数指针数组。
在第二个例子中,
int (*something)[n];
我认为我们可以使用简单的规则...
相关的IT技术内容。example int * (*ptr)()[];
start from ptr
ptr
是一个指向函数的指针。向右移动,现在是“)”,再向左移动,是“(”。走出来,向右走到“()”,然后向左移动,“它返回一个指向整数数组的指针”"。)
,现在向左走... 是*
"一个指针,指向" 向右走... 是)
,现在向左走... 是一个(
出来,向右走()
, 所以 "指向一个不带参数的函数" 向右走... 是[]
"并返回一个" 向右走;
结束,所以向左走... 是*
"指向" 向左走... 是int
"整数"。 - alx - recommends codidact
const
和volatile
这两个既重要又棘手的限定符。 - not-a-user