指向二维数组的指针

4
请看下面的代码片段:
#include <stdio.h>
#define ROW_SIZE 2
#define COL_SIZE 2

int main()
{
   int a[ROW_SIZE][COL_SIZE]={{1,2},{3,4}};

   // Base address:Pointer to the first element a 1D array
   printf("Base address of array:%p\n",a);

   //The value at the base address: should be the address of 1st 1D array
   printf("Value at the Base address:%p\n",*a);

   return 0;
}

获得的输出结果:

Sample Output:
Base address of array:0xbff77434
Value at the Base address:0xbff77434

一些情况下,我无法理解二维数组的基地址和基地址上的值(也就是一个指向一维数组的地址)相同的概念。请解释一下。

4
数组不是指针。 - Carl Norum
阅读 comp.lang.c FAQ 的第6部分。 - Keith Thompson
4个回答

8

数组不是指针,在C语言中,多维数组只是一组数组。在许多情况下,使用数组的名称会“衰减”为指向该数组第一个元素的指针。这就是您两个打印语句中发生的情况。在第一个情况中:

printf("Base address of array:%p\n",a);

a 变成了指向数组第一个元素的指针,也就是指向你的数组第一行的指针。在你的情况下,这意味着你会得到一个类型为int (*)[2]的指针。

在第二种情况下:

printf("Value at the Base address:%p\n",*a);

同样的衰减会发生,但是然后你会取消引用该指针。这意味着您将此int(*)[2]指针取消引用到第一行,留下一个数组(第一行)。该数组本身衰减为指向其第一个元素的指针,从而给您一个结果为int*指针(指向第一行的第一个元素)。
在两种情况下,地址都相同,因为这就是数组在内存中的布局方式。如果我们说您的2D数组从地址0开始,则它将如下所示(假设4字节的int类型):
 Address       Value
    0            1
    4            2
    8            3
   12            4

第一行的地址和第一行第一个元素的地址都是0


7
重新组织问题中的图表并整合之前的答案,我创建了以下答案。
一维数组
- 将包含4个整数的数组a视为a [4]。 - 基本规则是a和&a将指向相同的位置。但它们并不指向相同的类型。 - &a将指向整个数组,即int []。指针类型为int(*)[]。 - 当a退化为指针时,将指向数组的第一个元素,即int。指针类型为int *。
二维数组
- 将包含两个具有两个元素的1D数组的数组视为a [2] [2]。 - 由于维数增加,我们有了另一层层次结构,即&a,a和*a将指向相同的位置,但它们并不指向相同的类型。 - &a将指向整个数组,即int [] []。指针类型为int(*)[][]。 - 当a退化为指针时,将指向2D数组的第一个元素,即int []。指针类型为int(*)[]。 - 通过使用*a,我们正在取消引用指向1D数组的指针。因此,我们将有一个int *指向2D数组的第一个整数值。

0

我认为你的输出格式可能会让你感到困惑。你是对的,第一个数组元素的地址(0xbff77434)值(1)是不同的。%p 试图将两者都强制转换为“指针”格式,因此出现了混淆。

而且,卡尔也是正确的。

如果你想看看第一个元素中的内容,你可以使用以下任何一种方式:

printf("%i", a[0][0]);

int* p = &a[0][0];    // point 'p' to the beginning of 'a'
// (or)
int* p = a;           // saying "&a[0][0]" is the same as saying "a"
printf("%i", *p);     // here, the dereference is what you want

就一维数组和二维数组而言,这只是一种解释问题的方式。两者皆可。
int x[4];

int x[2][2];

创建4个“int大小”元素的连续块。在两种情况下,“x”表达式都指向第0个条目的地址(例如,数组的地址)。

0

二维数组 a[2][2] 可以看作是一个有4个元素的一维数组。想象一下当你将 a 强制转换为 int* 指针时会发生什么:

int a[2][2] = {{ 1, 2 }, { 3, 4 }};
int* p = (int*) a; // == { 1, 2, 3, 4 }

assert(a[1][0] == p[2] == 3); // true

int* a0 = a[0];  // the first row in the bidimensional array
int* p0 = &p[0]; // the first element in the monodimensional array

assert(*a0 == *p0 == 1); // true

// Or the long version:
assert(a[0][0] == *a0 == a0[0] == p[0] == *p0 == p0[0] == 1); // true

// And for the second array in a:
int* a1 = a[1]; // the second row in the bidimensional array
int p2 = &p[2]; // the third element in the monodimensional array

assert(a[1][0] == *a1 == a1[0] == p[2] == *p2 == p2[0] == 3); // true

数组aa[0]基本上指向同一个地址,但它们的类型传达了有关如何操作它们的信息。


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