数组指针与二维数组

2014-11-04

今天,偶遇到一C语言面试题,问题是求下面代码的输出:

    int main(void)  
    {  
        char aa[][3] = {'a','b','c','d','e','f'};  
        char (*p)[3] = aa;  
        p++;  

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

标准答案是d。由于太长时间没用过C语言了,有点懵,就把再学习c指针-int型指针及其他翻出来看了下。

下面一行一行解释下这段代码。

首先:

char aa[][3] = {'a','b','c','d','e','f'};

定义了一个2行3列的二维数组,我们把它想象成矩阵,第0行存储的是'a','b','c',第1行存储的是'd','e','f'。当然,这六个元素在内存中是依次排列、紧紧挨着的。

然后:

char (*p)[3] = aa;  

定义了一个名为p的数组指针数组指针是指该指针指向一个数组,[3]指明被指向的数组最小的大小。另外,有一个指针数组的概念,char *q[3]是一个指针数组,q是一个具有3个元素的数组,每个元素是一个指向char类型变量的指针。

p的默认值是aa数组第0行第0列元素的地址,也就是aa的首地址,p++将p向下转移了一行,让p的值变成了aa数组第1行第0列元素的地址,所以:

printf("%c\n",**p);  

输出d

我在上面代码的基础上加了些冗余的代码,也许更容易理解:

# include <stdio.h>
# include <stdlib.h>

/*
 * 
 */
int main(int argc, char** argv) {
    char aa[][3] = {'a','b','c','d','e','f'};   // aa[2][3]
    int i,j;
    for(i=0; i<2; i++) {
        for(j=0; j<3; j++) {
            printf("%c\n", aa[i][j]);
        }
    }

    char (*p)[3] = aa;  // 数组指针

    printf("---\n");
    printf("%p\n", p);  //输出地址值,每次运行,结果可能不同
    printf("%p\n", aa); // 和上一语句输出相同
    printf("---\n");

    printf("%c\n", (*p)[0]);  //a
    printf("%c\n", (*p)[1]);  //b
    printf("%c\n", (*p)[2]);  //c
    printf("%c\n", (*p)[3]);  //d
    printf("%c\n", (*p)[4]);  //e

    printf("---\n");

    printf("%c\n",**p);  //a
    printf("%c\n",**(p+1));  //d
    printf("%c\n",*(*(p+1)+1));  //aa[1][1]-> e

    p++;  
    printf("%c\n",**p);  //aa[1][0] -> d 
    return (EXIT_SUCCESS);
}

运行结果:

a
b
c
d
e
f
---
0x7fffa0bd1a70
0x7fffa0bd1a70
---
a
b
c
d
e
---
a
d
e
d

( 完 )

( 完 )