TypeCodes

指针数组和指针的指针(间级指针)实例分析

网上看到一个关于指向指针的指针变量(间级指针)和指针数组的分析题,感觉比较有代表性,所以摘录了下来自己分析了一番。

1 程序代码:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
 * 指针数组和指针的指针(间级指针)实例分析
 * @Filename: doubledimensionalarray.c
 * @Source  : 改动自网络
 */
#include <stdio.h>

int main( int argc, char * argv[] )
{
    int i = 0;

    //指针数组
    char *str[] = { "welcome", "to", "fortemedia", "Nanjing" };

    //sizeof查看指针数组str占用内存大小,输出sizeof(str)=[16],因为指针数组str里面存放的是4个指针,所以共4*4Bytes=16Bytes
    printf( "sizeof(str)=[%d]\n\n", sizeof(str) );

    //打印指针数组的内容
    for( ; i<4; i++ )
        printf( "str[%d]=[%s]\n", i, str[i] );

    printf( "\n" );

    //初始化指针的指针p,指向&str[1],即指针元素str[1]所在的地址,而指针元素str[1]又指向字符串"to",即其值是字符串"to"的地址
    char **p = str+1;

    //sizeof查看指向指针的指针变量p、指针变量*p和**p对应的字符所占用的内存大小
    printf( "sizeof(p)=[%d]\n", sizeof(p) );        //输出:sizeof(p)=[4]      因为p仍然只是一个指针变量(等价于&str[1])
    printf( "sizeof(*p)=[%d]\n", sizeof(*p) );      //输出:sizeof(*p)=[4]     因为*p同样只是一个指针变量(等价于str[1])
    printf( "sizeof(**p)=[%d]\n\n", sizeof(**p) );  //输出:sizeof(**p)=[1]    **p等价于*str[1],即值是字符't'

    printf( "*p=[%s]\n", *p );              //输出:  *p=[to]
    printf( "(**p)+1=[%c]\n", (**p)+1 );    //输出:  (**p)+1=[u]
    printf( "str[1]=[%s]\n", str[1] );      //输出:  str[1]=[to]
    printf( "*str[1]=[%c]\n", *str[1] );    //输出:  *str[1]=[t]

    //开始通过指针的指针变量p改变指针数组str中的内容
    str[0] = (*p++) + 2;                    //(*p++)即前面的*p=[to],所以(*p++)+2指向字符串"to"后面的字符串;执行完后,p=&str[2],即字符串"fortemedia"地址的地址
    str[1] = *(p+1);                        //*(p+1)等价于str[3],也就是此时str[1]指向了字符串"Nanjing"
    str[2] = p[1] + 3;                      //p[1]相当于*(p+1),指向字符串"Nanjing",所以右边相当于str[3]+3,也即str[2]指向了字符串"jing"
    str[3] = p[0] + ( str[2]-str[1] );      //p[0]相当于*p也即str[2],所以右边相当于*p+3也即str[2]+3,也就是字符串"jing"中从字符'g'开始的字符串

    printf( "\n" );

    //打印指针数组的内容
    for( i=0; i<4; i++ )
        printf( "str[%d]=[%s]\n", i, str[i] );

    return 0;
}

指针数组和指针的指针(间级指针)实例分析

2 分析总结

由于在上面的程序中,已经对重要内容都做了分析注释,所以这里再做一些其它的分析总结。

2.1 指针数组初始化的过程

程序通过char *str[] = { "welcome", "to", "fortemedia", "Nanjing" };初始化指针数组str时,实质是初始化了4个字符指针指向一个连续的内存块。而这个连续的内存块中,依次存储的内容是"welcome", "to", "fortemedia", "Nanjing"这4个字符串。

可以通过CodeBlocks调试,在watch窗口视图和memory窗口视图中查看内存状况。PS:这个连续的内存块(0x405064~0x40507a+8)存放这个4个字符串时,还包括了字符串结束标志符号'\0',即十六进制的0x00。

CodeBlocks调试watch窗口

CodeBlocks调试memory窗口

2.2 sizeof指针数组,查看占用内存大小

在程序中的第16行,由于指针数组里面实质存放的是指针,所以sizeof(指针数组)时,跟它的指针个数有关,即一个指针数组占用的内存大小是指针个数*4字节。这点跟二维数组不同,因为sizeof(二维数组)所占内存是元素类型*元素个数字节。

例如一个字符型二维数组char a[3][4]的大小为:1*12 = 12 字节;而一个整型二维数组int a[3][4]的大小为:4*12=48 字节。

2.3 sizeof多重指针,查看占用内存大小

在程序中的第28~30行,通过sizeof可以看到不管是指向指针的指针还是纯粹的单级指针,它始终只占用4字节内存大小。

2.4 间级指针(多重指针)和指针数组的关系

程序中第25行中,通过char **p = str+1;初始化指针的指针p,即p=&str[1],也即指针元素str[1]所在的地址。而指针元素str[1]又指向字符串"to",即其值是字符串"to"的地址0x40506c。

理解这点是关键,指针变量p初始化时,是把指针数组str中第二个指针的地址赋给p,而不是直接把字符串"to"的地址赋给p!其实,指针数组也是一个间级指针(二重指针)。

打赏支持

Comments »