C指针与2D数组

3
我正在学习C语言,我对二维数组指针感到困惑。
我有以下声明:
int a[3][5];
int *b[3][3];
int (*c)[3][5];
int *(d[3][5]);
int (*e[3])[5];

可以有人帮我澄清一下以下问题吗:
  1. 是否有有效的声明
  2. a,b,c,d,e的大小(假设在64位机器上,地址ID为8字节)
  3. 它们指向什么
  4. 如何访问2D数组中的元素
我对指向2D数组的指针的使用完全感到困惑......我猜其中一些是等效的......但有些可能不是好的实践。

可能是在C变量声明中括号的含义是什么?的重复问题。 - frslm
1
如果b是[3][5]而不是[3][3],那么b和d将是相同的。我假设你打算使用[3][5]? - Tom Karzes
一个2D数组是由1D数组构成的数组。例如,rows数个1D数组的数组。 int *b [3] [3]是指向类型为 int 的指针的2D数组。int (*c) [3] [5] 是指向3x5个int数组的指针。int *(d[3][5])*d[3][5]相同,而int (*e[3])[5]是指向3个int(其中每个有5个)的指针数组。 - David C. Rankin
1
@davidc.rankin 不: d与b相同(除了3和5)-括号没有影响,e是一个包含3个指针的数组,这些指针指向包含5个整数的数组。特别地,sizeof(e)为3*8 = 24。 - Tom Karzes
干得好,汤姆。 - David C. Rankin
1个回答

3

这些

int a[3][5];
int *b[3][5];

我想你的意思是确实是int *b [3] [5]而不是在你的问题中写成int *b [3] [3]. 有两个二维数组的声明。
第一个数组的元素类型为int。 第二个数组的元素类型为int *
要访问数组元素,可以使用下标,例如 a[i][j]b[i][j],其中i是范围内的索引[0,3)j 是范围内的索引[0, 5)。
对于第二个数组,要访问数组元素指向的对象,可以使用*b[i][j]之类的表达式。 sizeof( a )等于3 * sizeof( int[5] ),这又等于3 * 5 * sizeof( int )sizeof( b )等于3 * sizeof( int *[5] ),这又等于3 * 5 * sizeof( int *)
这个。
int (*c)[3][5];

这是一个指向类型为int[3][5]的二维数组的指针声明。

例如,您可以这样写:

int (*c)[3][5] = &a;

其中a是上面声明的二维数组。

要访问指向数组的元素,您可以使用以下语法。

( *c )[i][j]

This

int *(d[3][5]);

声明一个二维数组,其元素具有类型 int *。 这个声明与上面显示的声明是等价的。
int *b[3][5];

您可以将声明符括在括号中。因此,您甚至可以像这样编写数组d的声明:

int * (((d)[3])[5]);

This

int (*e[3])[5];

这是一个声明了一个包含3个指针数组的数组,每个指针数组的类型为int[5]。 使用typedef关键字可以简化该声明。

typedef int T[5]; 

数组声明可以重写为:
T * e[3];

这里有一个演示程序,展示了如何访问数组e中的元素。

#include <stdio.h>

int main( void )
{
    int a1[5] = { 1, 2, 3, 4, 5 };
    int a2[5] = { 10, 20, 30, 40, 50 };
    int a3[5] = { 100, 200, 300, 400, 500 };

    int(*e[3])[5] = { &a1, &a2, &a3 };

    for (size_t i = 0; i < sizeof( e ) / sizeof( *e ); i++)
    {
        for (int j = 0; j < sizeof(*e[i]) / sizeof(**e[i]); j++)
        {
            printf( "%3d ", ( *e[i] )[j] );
        }
        putchar( '\n' );
    }

    return 0;
}

程序输出为:
  1   2   3   4   5
 10  20  30  40  50
100 200 300 400 500

非常感谢您提供如此详细的解释!但是有没有解析指针声明的规则呢?我不想死记硬背。对于C语言专家来说,这可能很明显,但对我来说很难理解。 - Ziqi Liu
@ZiqiLiu 只需将最左边的数组替换为指针即可。例如:int ( a[n1] )[n2][n3]; int ( *p )[n2][n3] = a; - Vlad from Moscow
这个声明是否也会分配内存空间?它是否为3个int数组指针和每个指针上的y个整数创建内存空间?如果是这样,那么这个内存将如何组织? - etienz
@etienz 这里创建了一个包含三个指针的数组,没有其他内容。 - Vlad from Moscow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接