C语言 以这种方式声明和初始化指针需要什么:int (*p)[n]



我正在学习指针算法,并且有一个关于精确地利用指针处理 2D 数组列的示例。为此,代码显示了指针的新声明,下面是代码片段:

int a[NUM_ROWS][NUM_COLS], (*p) [NUM_COLS], i;
...
for (p = &a[0]; p < &a[NUM_ROWS]; p++)
(*p)[i] = 0;

这个指针((*p([NUM_COLS](的行为对我来说很奇怪,因为我刚刚了解到增加指针就像递增数组下标一样,允许您处理该指针指向的数组。所以这不是一个常规的指针吗?

大小(以字节为单位(是相同的,但是鉴于它在for 循环中分配时表示整行,该声明涉及什么?

语法如下

int (*p)[NUM_COLS];

本质上定义了一个指针p它是指向带有NUM_COLS元素的ints 数组的指针。

因此,它可以用作

int arr[NUM_COLS] = {0};
p = &arr;

这与所有其他指针具有相同的属性,

  • 指针的类型为int (*)[NUM_COLS]
  • 这个指针指向的实例的大小是int [NUM_COLS],即int的大小乘以NUM_COLS

正如@SouravHhosh所写,它定义了指向整数数组的指针。任何指针算术都是数组大小的乘法。

https://onlinegdb.com/Skg_6cRpS

T (*p)[N];

p声明为指向T的 N 元素数组的指针。 您主要在以下上下文中看到它们:

  • 作为更高维数组表达式"衰减"为指针表达式的结果;
  • 为更高维度的阵列分配内存时;

作为前者的示例,请考虑以下代码:

void foo( int (*p)[3] )
{
// do something with p
}
int main( void )
{
int arr[2][3];
foo( arr );
}

除非它是sizeof或一元&运算符的操作数,或者是用于初始化声明中字符数组的字符串文本,否则类型为"T的 N 元素数组"的表达式将被转换("衰减"(为"指向T的指针"类型的表达式,并且表达式的值将是数组第一个元素的地址。

当您将表达式arr作为参数传递给foo时,它从类型"int的 3 元素数组的 2 元素数组"(int [2][3]( 转换为"指向int的 3 元素数组的指针"(int (*)[3](。 因此,该函数实际上接收一个指针值,而不是一个数组。

因为指向数组语法的指针有点丑陋和繁琐,所以你可以交替使用

void foo( int p[][3] ) { ... }

用于声明,但仅在函数参数声明中。

作为后者的示例,如果要动态声明 2D 数组,可以这样做:

int (*p)[3] = malloc( 2 * sizeof *p );

它为 2x3int数组分配空间,并将指向该空间的指针分配给p表达式p的类型是"指向 3 元素数组的指针int",因此*p的类型是"int的 3 元素数组"。

请记住,数组下标操作a[i]定义为*(a + i)- 给定起始地址ai元素(不是字节(与该地址偏移并取消引用结果1。 因此,可以得出这样的结论:

*p == *(p + 0) == p[0]

意义

(*p)[i] == (*(p + 0))[i] == (p[0])[i] == p[0][i]

因此,在为p分配内存后,您可以像任何 2D 数组一样索引到它:

for ( size_t i = 0; i < 2; i++ )
for ( size_t j = 0; j < 3; j++ )
p[i][j] = some_value;

一般规则:

T *a[N];    // a is an N-element array of pointer to T
T (*a)[N];  // a is a pointer to an N-element array of T
T *f();     // f is a function returning a pointer to T
T (*f)();   // f is a pointer to a function returning T

由于下标[]和函数调用()运算符的优先级高于一元*,因此*a[i]将被解析为*(a[i])*f()将被解析为*(f())。 如果要将a视为指向数组的指针,f视为指向函数的指针,则必须使用括号将*运算符与标识符显式分组 -(*a)[i](*f)()


  1. C 源自早期称为 B 的语言。 在 B 中,数组具有指向第一个元素的显式指针,并且该指针绑定到数组变量。 因此,在 B 中,*(a + i)语法是有意义的,因为a始终是一个指针。 当 Ritchie 设计 C 时,他不想在数组中保留显式指针,因此他引入了数组表达式"衰减"到指针的规则,除非在特定情况下。

最新更新