混淆二维数组

时间:2012-09-05 17:54:12

标签: c multidimensional-array

请考虑以下2-D阵列:

int array[2][2] = {
                    {1,2},
                    {3,4}
                  };

根据我的理解: - 'array'表示二维数组的基地址(与数组的第一个元素的地址相同,即数组[0] [0])。

  • 内存中二维数组的实际安排就像一个大型的一维数组。

  • 现在,我知道base address = array。因此,我应该能够到达包含元素的内存块:array [0] [0]。

  • 如果我忘记了2-D阵列的事情&尝试将此数组视为一个简单的1-D数组: array [0] = *(array + 0)给出第一个数组的基地址&不是元素数组[0] [0]。为什么呢?

  • 2-D数组不存储任何内存地址(如指针数组)。

  • 如果我知道基地址,我必须能够以线性1-维数组的形式访问此内存。

请帮我澄清这个疑问。

感谢。

5 个答案:

答案 0 :(得分:5)

“你不要害怕激素arythmethyc”......

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)&array[0][0];
int i;
for (i = 0; i < 4; i++) {
    printf("%d\n", ptr[i]);
}

为什么这样做? C标准规定多维数组在内存中是连续的。这意味着,就其元素的顺序而言,2D数组的排列方式类似于

array[0][0]
array[0][1]
array[1][0]
array[1][1]

当然,如果你把数组的地址作为指向int的指针(int *,让它命名为ptr),那么这些项的地址如下:

ptr + 0 = &array[0][0]
ptr + 1 = &array[0][1]
ptr + 2 = &array[1][0]
ptr + 3 = &array[1][1]

这就是为什么它最终有效。

答案 1 :(得分:5)

array[0]是一维数组。其地址与array的地址相同,与array[0][0]的地址相同:

assert((void*)&array == (void*)&(array[0]));
assert((void*)&array == (void*)&(array[0][0]));

由于array[0]是一个数组,因此您无法将其分配给变量,也不能将其传递给函数(如果您尝试这样做,那么您将传递指向第一个元素的指针代替)。你可以通过查看(array[0])[0](array[0])[1](括号是多余的)来观察它是一个数组。

printf("%d %d\n", (array[0])[0], (array[0])[1]);

您可以观察到它的大小是2 int个对象的大小。

printf("%z %z %z\n", sizeof(array), sizeof(array[0]), sizeof(array[0][0]));

这是一个代表内存布局的图表:

+-------------+-------------+-------------+-------------+
|      1      |      2      |      3      |      4      |
+-------------+-------------+-------------+-------------+
 `array[0][0]' `array[0][1]' `array[1][0]' `array[1][1]'
`---------array[0]---------' `---------array[1]---------'
`-------------------------array-------------------------'

答案 2 :(得分:3)

  1. 内存中二维数组的实际安排就像一个大型的一维数组。

    是的,存储区域就像1D arrary一样是连续的。但索引方法略有不同。

    2-D[0][0] = 1-D[0] 
    
    2-D[0][1] = 1-D[1] 
    
    ... 
    
    2-D[i][j] = 1-D[ i * rowsize + j]
    
    ...
    
  2. 如果我忘记了2-D阵列的事情&amp;尝试将此数组视为一个简单的1-D数组:array [0] = *(array + 0)给出第一个数组的基地址&amp;不是元素数组[0] [0]。为什么呢?
    *(array + 0)表示指向数组的指针。这种格式的第一个元素索引应该是*((* array + 0)+0)。

    所以最后它应该是*(* array)

  3. 二维数组不存储任何内存地址(如指针数组)。   当然可以 。例如,

    int * array[3][3] ={ null, };
    
  4. 如果我知道基地址,我必须能够以线性1-维数组的形式访问此内存。

    使用这个正式的2-D [i] [j] = 1-D [i * rowsize + j] ......

答案 3 :(得分:1)

数组不是指针。

在大多数情况下 1 ,类型为“{-1}}的N元素数组”的表达式将被转换(“衰变”)为表达式输入“指向T的指针”,表达式的值将是数组第一个元素的地址。

表达式 T的类型是“array的2元素数组的2元素数组”。根据上面的规则,在大多数情况下,这将衰减为“指向intint}的2元素数组。这意味着表达式int (*)[2]的类型(并通过扩展名) ,*array*(array + 0))是“array[0]的2元素数组”,而后者将衰减为int类型。

因此,int *会在*(array + i)之后为您提供i' 2元素数组int (即,第一个int的元素数组位于arrayarray[0]),而*(array + 0)的第二个2元素数组位于intarray[1])。

如果你想将*(array + 1)视为array的一维数组,你必须按照

的方式进行一些铸造体操。
int

int *p = (int *) array;
int x = p[0];

<小时/> 1。例外情况是数组表达式是int x = *((int *) array + 0); 或一元sizeof运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字。

答案 4 :(得分:0)

我喜欢H2CO3的回答。但您也可以将指向数组的指针视为可递增变量,如下所示:

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 4; i++) 
{
    printf("%d\n", *ptr);
    ptr++;  
}

++运算符可以很好地处理指针。它会将指针增加一个类型的地址,或者在这种情况下为int的大小。

小心必须始终与c中的数组一起使用,以下编译就好了:

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 100; i++)  //Note the 100
{
    printf("%d\n", *ptr);
    ptr++;  
}

这会溢出数组。如果你写这个,你可以破坏程序中的其他值,包括for循环中的i和指针本身的地址。