指针数组和数组指针

Tutorial: C与汇编 Category: C语言 Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0
1. 指针数组
char* a = "hello";                   // 常量区(不支持修改)存储 hello, 将首地址给 a;
char* arr[2] = {"abcdef","hello"};   // 常量区存储数组(不支持修改), 将首地址给arr, 数组里面存放的是两个字符串的地址,而不是字符串
2. 数组指针
#include <stdio.h>

int main()
{
    int arr[] = {1, 2, 3};
    int *p1 = &arr[0];     // 简写为 int *p1 = arr;
    int *p2 = (int *)&arr; // int (*)[3], 数组指针
    return 0;
}

0040D76D   lea         eax,[ebp-0Ch]
0040D770   mov         dword ptr [ebp-10h],eax
7:        int *p2 = (int *)&arr;
0040D773   lea         ecx,[ebp-0Ch]
0040D776   mov         dword ptr [ebp-14h],ecx
3. 定义
// 一维数组指针
int(*px)[5]
char(*px)[3]

// 二维数组指针
int(*px)[2][2]

// 三维数组指针
int(*px)[3][3][3]

int *p[5]:   p 是一个有5个元素的数组,每个元素都是 int 类型的指针
int (*p)[5]: 一个指针,指向数组
4. 赋值: 数组指针也是指针,可以复制,可以自加自减
#include <stdio.h>

int main()
{
    int(*px1)[5];
    char(*px2)[3];
    int(*px3)[2][2];
    int(*px4)[3][3][3];

    px1 = (int(*)[5])1;
    px2 = (char(*)[3])1;
    px3 = (int(*)[2][2])1;
    px4 = (int(*)[3][3][3])1;

    px1++;
    px2++;
    px3++;
    px4++;
    printf("%d %d %d %d\n", px1, px2, px3, px4);

    return 0;
}

5:        int(*px1)[5];
6:        char(*px2)[3];
7:        int(*px3)[2][2];
8:        int(*px4)[3][3][3];
9:
10:       px1 = (int(*)[5])1;
0040D758   mov         dword ptr [ebp-4],1 // 指针都是4字节
11:       px2 = (char(*)[3])1;
0040D75F   mov         dword ptr [ebp-8],1
12:       px3 = (int(*)[2][2])1;
0040D766   mov         dword ptr [ebp-0Ch],1
13:       px4 = (int(*)[3][3][3])1;
0040D76D   mov         dword ptr [ebp-10h],1
14:
15:       px1++;
0040D774   mov         eax,dword ptr [ebp-4]
0040D777   add         eax,14h                 // 1 + 20 = 21
0040D77A   mov         dword ptr [ebp-4],eax
16:       px2++;
0040D77D   mov         ecx,dword ptr [ebp-8]
0040D780   add         ecx,3                   // 1 + 3 = 4
0040D783   mov         dword ptr [ebp-8],ecx
17:       px3++;
0040D786   mov         edx,dword ptr [ebp-0Ch]
0040D789   add         edx,10h                 // 1 +  2 * 2 * 4 = 17
0040D78C   mov         dword ptr [ebp-0Ch],edx
18:       px4++;
0040D78F   mov         eax,dword ptr [ebp-10h]
0040D792   add         eax,6Ch                 // 1 + 3 * 3 * 3 * 4 = 109
0040D795   mov         dword ptr [ebp-10h],eax
19:       printf("%d %d %d %d\n", px1, px2, px3, px4);
0040D798   mov         ecx,dword ptr [ebp-10h]
0040D79B   push        ecx
0040D79C   mov         edx,dword ptr [ebp-0Ch]
0040D79F   push        edx
0040D7A0   mov         eax,dword ptr [ebp-8]
0040D7A3   push        eax
0040D7A4   mov         ecx,dword ptr [ebp-4]
0040D7A7   push        ecx
0040D7A8   push        offset string "%d %d %d %d\n" (00422fa4)
0040D7AD   call        printf (0040d6c0)
0040D7B2   add         esp,14h
5. 不用强转
  • 源码
#include <stdio.h>

int main()
{
    int(*px1)[5];
    char(*px2)[3];
    int(*px3)[2][2];
    int(*px4)[3][3][3];

    int arr1[5] = {1, 2, 3, 4, 5};
    char arr2[3] = {'a', 'b', 'c'};
    int arr3[2][2] = {{1, 2}, {3, 4}};
    int arr4[3][3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

    px1 = &arr1;
    px2 = &arr2;
    px3 = &arr3;
    px4 = &arr4;
    printf("Add before: %x %x %x %x\n", px1, px2, px3, px4);
    // 19FF10 19FF0C 19FEFC 19FE90

    px1++;
    px2++;
    px3++;
    px4++;
    printf("Add after: %x %x %x %x\n", px1, px2, px3, px4);
    // 19FF24 19FF0F 19FF0C 19FEFC

    return 0;
}
  • 汇编
5:        int(*px1)[5];
6:        char(*px2)[3];
7:        int(*px3)[2][2];
8:        int(*px4)[3][3][3];
9:
10:       int arr1[5] = {1, 2, 3, 4, 5};
0040D75E   mov         dword ptr [ebp-24h],1 // 首地址
0040D765   mov         dword ptr [ebp-20h],2
0040D76C   mov         dword ptr [ebp-1Ch],3
0040D773   mov         dword ptr [ebp-18h],4
0040D77A   mov         dword ptr [ebp-14h],5
11:       char arr2[3] = {'a', 'b', 'c'};
0040D781   mov         byte ptr [ebp-28h],61h // 首地址
0040D785   mov         byte ptr [ebp-27h],62h
0040D789   mov         byte ptr [ebp-26h],63h
12:       int arr3[2][2] = {{1, 2}, {3, 4}};
0040D78D   mov         dword ptr [ebp-38h],1 // 首地址
0040D794   mov         dword ptr [ebp-34h],2
0040D79B   mov         dword ptr [ebp-30h],3
0040D7A2   mov         dword ptr [ebp-2Ch],4
13:       int arr4[3][3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
0040D7A9   mov         dword ptr [ebp-0A4h],1 // 首地址
0040D7B3   mov         dword ptr [ebp-0A0h],2
0040D7BD   mov         dword ptr [ebp-9Ch],3
0040D7C7   mov         ecx,6
0040D7CC   xor         eax,eax
0040D7CE   lea         edi,[ebp-98h]
0040D7D4   rep stos    dword ptr [edi]
0040D7D6   mov         dword ptr [ebp-80h],4
0040D7DD   mov         dword ptr [ebp-7Ch],5
0040D7E4   mov         dword ptr [ebp-78h],6
0040D7EB   mov         ecx,6
0040D7F0   xor         eax,eax
0040D7F2   lea         edi,[ebp-74h]
0040D7F5   rep stos    dword ptr [edi]
0040D7F7   mov         dword ptr [ebp-5Ch],7
0040D7FE   mov         dword ptr [ebp-58h],8
0040D805   mov         dword ptr [ebp-54h],9
0040D80C   mov         ecx,6
0040D811   xor         eax,eax
0040D813   lea         edi,[ebp-50h]
0040D816   rep stos    dword ptr [edi]
14:
15:       px1 = &arr1;
0040D818   lea         eax,[ebp-24h]              // 首地址
0040D81B   mov         dword ptr [ebp-4],eax
16:       px2 = &arr2;
0040D81E   lea         ecx,[ebp-28h]              // 首地址
0040D821   mov         dword ptr [ebp-8],ecx
17:       px3 = &arr3;
0040D824   lea         edx,[ebp-38h]              // 首地址
0040D827   mov         dword ptr [ebp-0Ch],edx
18:       px4 = &arr4;
0040D82A   lea         eax,[ebp-0A4h]             // 首地址
0040D830   mov         dword ptr [ebp-10h],eax
19:       printf("Add before: %x %x %x %x\n", px1, px2, px3, px4);
0040D833   mov         ecx,dword ptr [ebp-10h]
0040D836   push        ecx
0040D837   mov         edx,dword ptr [ebp-0Ch]
0040D83A   push        edx
0040D83B   mov         eax,dword ptr [ebp-8]
0040D83E   push        eax
0040D83F   mov         ecx,dword ptr [ebp-4]
0040D842   push        ecx
0040D843   push        offset string "Add before: %d %d %d %d\n" (00422fbc)
0040D848   call        printf (0040d6c0)
0040D84D   add         esp,14h
20:
21:       px1++;
0040D850   mov         edx,dword ptr [ebp-4]
0040D853   add         edx,14h
0040D856   mov         dword ptr [ebp-4],edx
22:       px2++;
0040D859   mov         eax,dword ptr [ebp-8]
0040D85C   add         eax,3
0040D85F   mov         dword ptr [ebp-8],eax
23:       px3++;
0040D862   mov         ecx,dword ptr [ebp-0Ch]
0040D865   add         ecx,10h
0040D868   mov         dword ptr [ebp-0Ch],ecx
24:       px4++;
0040D86B   mov         edx,dword ptr [ebp-10h]
0040D86E   add         edx,6Ch
0040D871   mov         dword ptr [ebp-10h],edx
25:       printf("Add after: %x %x %x %x\n", px1, px2, px3, px4);
0040D874   mov         eax,dword ptr [ebp-10h]
0040D877   push        eax
0040D878   mov         ecx,dword ptr [ebp-0Ch]
0040D87B   push        ecx
0040D87C   mov         edx,dword ptr [ebp-8]
0040D87F   push        edx
0040D880   mov         eax,dword ptr [ebp-4]
0040D883   push        eax
0040D884   push        offset string "Add after: %d %d %d %d\n" (00422fa4)
0040D889   call        printf (0040d6c0)
0040D88E   add         esp,14h
6. 获取和修改数组的值
#include <stdio.h>

int main()
{

    int arr[5] = {1, 2, 3, 4, 5};
    int(*px)[5] = &arr;
    printf("%x %x\n", (*px)[0], px[0][0]);

    (*px)[0] = 10;
    printf("%x %x\n", (*px)[0], px[0][0]);

    px++;
    printf("%x %x\n", (*px)[0], px[0][0]);

    return 0;
}


6:        int arr[5] = {1, 2, 3, 4, 5};
0040D758   mov         dword ptr [ebp-14h],1        // 19FF20
0040D75F   mov         dword ptr [ebp-10h],2
0040D766   mov         dword ptr [ebp-0Ch],3
0040D76D   mov         dword ptr [ebp-8],4
0040D774   mov         dword ptr [ebp-4],5
7:        int(*px)[5] = &arr;
0040D77B   lea         eax,[ebp-14h]                // 19FF20
0040D77E   mov         dword ptr [ebp-18h],eax      // 19FF1C(19FF20)
8:        printf("%x %x\n", (*px)[0], px[0][0]);
0040D781   mov         ecx,dword ptr [ebp-18h]      // [19FF1C]
0040D784   mov         edx,dword ptr [ecx]          // [19FF20] = 1
0040D786   push        edx
0040D787   mov         eax,dword ptr [ebp-18h]      // [19FF1C]
0040D78A   mov         ecx,dword ptr [eax]          // [19FF20] = 1
0040D78C   push        ecx
9:
10:       (*px)[0] = 10;
0040D79A   mov         edx,dword ptr [ebp-18h]
0040D79D   mov         dword ptr [edx],0Ah
11:       printf("%x %x\n", (*px)[0], px[0][0]);
0040D7A3   mov         eax,dword ptr [ebp-18h]
0040D7A6   mov         ecx,dword ptr [eax]
0040D7A8   push        ecx
0040D7A9   mov         edx,dword ptr [ebp-18h]
0040D7AC   mov         eax,dword ptr [edx]
0040D7AE   push        eax
12:
13:       px++;
0040D7BC   mov         ecx,dword ptr [ebp-18h]     // 19FF20
0040D7BF   add         ecx,14h                     // 4 * 5 = 20, 19FF34 = ebp
0040D7C2   mov         dword ptr [ebp-18h],ecx
14:       printf("%x %x\n", (*px)[0], px[0][0]);
0040D7C5   mov         edx,dword ptr [ebp-18h]     // 19FF34
0040D7C8   mov         eax,dword ptr [edx]         // 0019FF34  74 FF 19 00 39 11
0040D7CA   push        eax                         // 19FF74
0040D7CB   mov         ecx,dword ptr [ebp-18h]
0040D7CE   mov         edx,dword ptr [ecx]
0040D7D0   push        edx                         // 19FF74
7. 指针的变化
#include <stdio.h>

int main()
{
    int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int(*px)[3] = &arr[0];                   // 指向二维数组的第一个数组(一维数组)
    printf("%d %d\n", (*px)[0], (*px)[2]);   // 打印数组的第0,2 项:1 3

    px++;                                    // px 是指向一维数组的指针,自加的话, 3 * 4 = 12, 指向了 arr 的第二项:一维数组
    printf("%d %d\n", (*px)[0], (*px)[2]);   // 打印数组的第0,2 项:4 6

    return 0;
}

5:        int arr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
0040D758   mov         dword ptr [ebp-24h],1   // 第一项首地址
0040D75F   mov         dword ptr [ebp-20h],2
0040D766   mov         dword ptr [ebp-1Ch],3
0040D76D   mov         dword ptr [ebp-18h],4   // 第二项首地址
0040D774   mov         dword ptr [ebp-14h],5
0040D77B   mov         dword ptr [ebp-10h],6
0040D782   mov         dword ptr [ebp-0Ch],7   // 第三项首地址
0040D789   mov         dword ptr [ebp-8],8
0040D790   mov         dword ptr [ebp-4],9
6:        int(*px)[3] = &arr[0];
0040D797   lea         eax,[ebp-24h]               // &1
0040D79A   mov         dword ptr [ebp-28h],eax
7:        printf("%d %d\n", (*px)[0], (*px)[2]);
0040D79D   mov         ecx,dword ptr [ebp-28h]
0040D7A0   mov         edx,dword ptr [ecx+8]
0040D7A3   push        edx
0040D7A4   mov         eax,dword ptr [ebp-28h]
0040D7A7   mov         ecx,dword ptr [eax]
0040D7A9   push        ecx
0040D7AA   push        offset string "abcdef" (00422fa4)
0040D7AF   call        printf (0040d6c0)
0040D7B4   add         esp,0Ch
8:
9:        px++;
0040D7B7   mov         edx,dword ptr [ebp-28h]
0040D7BA   add         edx,0Ch
0040D7BD   mov         dword ptr [ebp-28h],edx
10:       printf("%d %d\n", (*px)[0], (*px)[2]);
0040D7C0   mov         eax,dword ptr [ebp-28h]
0040D7C3   mov         ecx,dword ptr [eax+8]
0040D7C6   push        ecx
0040D7C7   mov         edx,dword ptr [ebp-28h]
0040D7CA   mov         eax,dword ptr [edx]
0040D7CC   push        eax
0040D7CD   push        offset string "abcdef" (00422fa4)
0040D7D2   call        printf (0040d6c0)
0040D7D7   add         esp,0Ch
8. 深入理解
#include <stdio.h>

int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int(*px)[2][2] = (int(*)[2][2])arr;      // 强转为2维数组,因为数组在内存中也是按顺序排列的

    printf("%d\n", (*px)[1][1]);             // 4

    px++;                                    // +16
    printf("%d\n", (*px)[1][1]);             // 8

    return 0;
}

5:        int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
0040D758   mov         dword ptr [ebp-24h],1
0040D75F   mov         dword ptr [ebp-20h],2
0040D766   mov         dword ptr [ebp-1Ch],3
0040D76D   mov         dword ptr [ebp-18h],4
0040D774   mov         dword ptr [ebp-14h],5
0040D77B   mov         dword ptr [ebp-10h],6
0040D782   mov         dword ptr [ebp-0Ch],7
0040D789   mov         dword ptr [ebp-8],8
0040D790   mov         dword ptr [ebp-4],9
6:        int(*px)[2][2] = (int(*)[2][2])arr;
0040D797   lea         eax,[ebp-24h]                       // 首地址
0040D79A   mov         dword ptr [ebp-28h],eax
7:
8:        printf("%d\n", (*px)[1][1]);
0040D79D   mov         ecx,dword ptr [ebp-28h]            // &arr[0][0]
0040D7A0   mov         edx,dword ptr [ecx+0Ch]            // 3 * 4 = 12, 第0项 -> 第3项
0040D7A3   push        edx
0040D7A4   push        offset string "abcdef" (00422fa4)
0040D7A9   call        printf (0040d6c0)
0040D7AE   add         esp,8
9:
10:       px++;
0040D7B1   mov         eax,dword ptr [ebp-28h]
0040D7B4   add         eax,10h                          // 2 * 2 * 4 = 16, 加过后在放回去
0040D7B7   mov         dword ptr [ebp-28h],eax
11:       printf("%d\n", (*px)[1][1]);
0040D7BA   mov         ecx,dword ptr [ebp-28h]
0040D7BD   mov         edx,dword ptr [ecx+0Ch]          // 在现在的基础上,加 12, 同上
0040D7C0   push        edx
0040D7C1   push        offset string "abcdef" (00422fa4)
0040D7C6   call        printf (0040d6c0)
0040D7CB   add         esp,8