Hit9 Blog Wiki Project Links Archives Resumé
Page: First UP Pre Next Back

C语言二维数组结构探析

Fork me on GitHub

允许转载, 但转载请注明出处

Date:2012-10-24

看下面的代码:

#include <stdio.h>
int main(int argc, const char *argv[])
{
    int a[2][3] = {
        {1, 2, 3}, 
        {4, 5, 6}
    }; 

    printf("%p\n", a);
    printf("%p\n", *a);
    return 0;
}

会发现a和*a竟然是一样的.

其实这6个数字是连续存储的:

 +---+---+---+---+---+---+
 | 1 | 2 | 3 | 4 | 5 | 6 |
 +---+---+---+---+---+---+

那就是说,存储的跟一维数组完全一样.

如果我们这么定义 a[2][3]:

int a[2][3] = {
        1, 2, 3,
        4, 5, 6
    };

会发现编译和执行都正常.验证了这6个数据是连续存储的.

而a存储着a[0][0]的地址.

看下面的代码:

int main(){
    int a[1][2][3] = {
        1, 2, 3,
        4, 5, 6
    };
    printf("%p\n", a);
    printf("%p\n", *a);
    printf("%p\n", **a);
    printf("%d\n", ***a);
    return 0;                                                             
}

会发现a,*a,**a都是一样的.最后一个输出数据1.

所以这就摸清了规律了.

所以对上面的定义方式来说,a根本不是一个二级指针.

既然是连续存储,加入2句code:(存储方式就是一维数组的方式)

int *b = (int *)a; 
printf("%d\n", *b); 

会看到输出了1.也就是,只要这种存储方式,数组名永远是首元素的地址.上式中把a强制赋值给了b,b记录着a[0][0]的地址

那对于下面的code呢?,并不是上面我们讨论的存储方式:

#include<stdio.h>

int main(){
    int m[3] = {1, 2, 3}; 
    int n[3] = {4, 5, 6}; 
    int *a[2] = {m, n}; 
    return 0;                                                             
}

并且这里的a与*a也不相等.

这个问题很不好理解.欢迎交流!

---over----


Support:mkdwiki