【技术研究】指针细节

TEC

Posted by Corax on November 19, 2023

指针

  1. 数组名是第零个元素的指针常量
  2. 二维数组是元素是一维数组的数组。
int ary[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40}, 
        {100, 200, 300, 400}, 
    };
printf("%p\r\n", ary);

ary[3] [4]的元素是int[4]

这里的数组名ary就是第零个元素,即{1, 2, 3, 4}的指针常量

ary就是int[4]类型指针常量

因为是指针常量而不是指针变量,所以没有所谓的地址。

打印结果如下

image-20231120142551387

printf("%p\r\n", *ary);

继续刚刚的,ary是一维数组int[4]的指针

*ary 对ary取内容就是 得到Int[4]数组(是得到这个数组了,非指针常量)

*ary 也是一个数组名了,而它是一个一维数组的数组名,他的元素就是int数据

而数组名是第零个元素的指针常量

所以*ary就是int类型的指针常量。

打印如下

image-20231120143523243

printf("%p\r\n", &ary);

任何类型的变量取地址得到该类型的指针

对二维数组取地址 得到二维数组的指针。

&ary得到 int[3] [4]类型的指针,它已经是一个指针了,而非数组名。

打印如下

image-20231120143750900

所以虽然打印出来的结果都一样,但是实际上他们对ary的解释方式各不相同,所以如下。

printf("%p\r\n", ary + 1);
printf("%p\r\n", *ary + 1);
printf("%p\r\n", &ary + 1);

需要注意的是,xxx + n实际上就是

(int)ary + sizeof(int[n]) * 1

所以这里的ary + 1,应该是对于int[4]

(int)ary + sizeof(int[4]) * 1

image-20231120144324429

就是箭头所指的地址,打印看看

image-20231120144351412

正确

printf("%p\r\n", *ary + 1);

同理

刚刚分析了 *ary 是int类型的指针常量

(int)ary + sizeof(int) * 1

所以应该在这

image-20231120145433412

确实

image-20231120145441382

printf("%p\r\n", &ary + 1);

直接获得了二维数组的指针了,所以加上的就是

(int)ary + sizeof(int[3][4]) * 1

image-20231120145627138

应该在这

正确

image-20231120145644599

再来搞搞

printf("%p\r\n", ary[0] + 1);
  1. 数组名是第零个元素的指针常量
  2. 二维数组是元素是一维数组的数组。

所以ary[0]是指向int类型的指针常量,加上一

(int)ary + sizeof(int) * 1

所以就是

image-20231120150133227

再来

printf("%p\r\n", (*(ary + 1))[1]);

这个里面ary + 1

指针加整型 等于 这个类型的指针

所以这里等于的是 指向第二个一维数组的int[4]指针

image-20231120151127090

然后对他取内容 就是这个数组了 [1]就是20

而如果没有*

printf("%p\r\n", ((ary + 1))[1]);

取地址符展开变成 指向第二个一维数组的int[4]指针 再加1

指向第三个一维数组

image-20231120171142571

int ary[3][4] = {
        {1, 2, 3, 4},
        {10, 20, 30, 40}, 
        {100, 200, 300, 400}, 
    };
    int (*p)[4] = ary;
    int (*pAry)[3][4] = &ary;
    
    printf("%p\r\n", p);
    printf("%p\r\n", *p);
    printf("%p\r\n", pAry);
    printf("%p\r\n", *pAry);
    printf("%p\r\n", **pAry);

    printf("%p\r\n", p + 1);
    printf("%p\r\n", *p + 1);
    printf("%p\r\n", pAry + 1);
    printf("%p\r\n", *pAry + 1);
    printf("%p\r\n", **pAry + 1);

打印

image-20231120172321450

image-20231120172336135

五条对应的就是

  1. 一个指向int[4]的指针
  2. 一个是读int[4]内容,也就是指向int的指针
  3. 一个是指向int[3] [4]的指针
  4. 一个是读int[3] [4]内容,也就是指向int[4]的指针
  5. 一个是int[3] [4]内容,再读int[4]的,指向int的指针。

修改指针 二级指针

image-20231120174742871

image-20231120175202206

其实char *aryPointer[3]就是

**aryPointer 所以aryPointer(写法区别)才是

char *的指针常量,也用二级指针来指向一级指针

命令行三个参数

image-20231120175541464

image-20231120175448741

分别是返回地址

argc 后面argv 字符型指针数组的总个数

argv 字符型指针数组

envp 环境变量

以下是argv的全路径

image-20231120175545969