指针
- 数组名是第零个元素的指针常量。
- 二维数组是元素是一维数组的数组。
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]类型的指针常量
因为是指针常量而不是指针变量,所以没有所谓的地址。
打印结果如下

printf("%p\r\n", *ary);
继续刚刚的,ary是一维数组int[4]的指针
*ary 对ary取内容就是 得到Int[4]数组(是得到这个数组了,非指针常量)
*ary 也是一个数组名了,而它是一个一维数组的数组名,他的元素就是int数据
而数组名是第零个元素的指针常量。
所以*ary就是int类型的指针常量。
打印如下

printf("%p\r\n", &ary);
任何类型的变量取地址得到该类型的指针
对二维数组取地址 得到二维数组的指针。
&ary得到 int[3] [4]类型的指针,它已经是一个指针了,而非数组名。
打印如下

所以虽然打印出来的结果都一样,但是实际上他们对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

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

正确
printf("%p\r\n", *ary + 1);
同理
刚刚分析了 *ary 是int类型的指针常量
(int)ary + sizeof(int) * 1
所以应该在这

确实

printf("%p\r\n", &ary + 1);
直接获得了二维数组的指针了,所以加上的就是
(int)ary + sizeof(int[3][4]) * 1

应该在这
正确

再来搞搞
printf("%p\r\n", ary[0] + 1);
- 数组名是第零个元素的指针常量。
- 二维数组是元素是一维数组的数组。
所以ary[0]是指向int类型的指针常量,加上一
(int)ary + sizeof(int) * 1
所以就是

再来
printf("%p\r\n", (*(ary + 1))[1]);
这个里面ary + 1
指针加整型 等于 这个类型的指针
所以这里等于的是 指向第二个一维数组的int[4]指针

然后对他取内容 就是这个数组了 [1]就是20
而如果没有*
printf("%p\r\n", ((ary + 1))[1]);
取地址符展开变成 指向第二个一维数组的int[4]指针 再加1
指向第三个一维数组

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);
打印


五条对应的就是
- 一个指向int[4]的指针
- 一个是读int[4]内容,也就是指向int的指针
- 一个是指向int[3] [4]的指针
- 一个是读int[3] [4]内容,也就是指向int[4]的指针
- 一个是int[3] [4]内容,再读int[4]的,指向int的指针。
修改指针 二级指针


其实char *aryPointer[3]就是
**aryPointer 所以aryPointer(写法区别)才是
char *的指针常量,也用二级指针来指向一级指针
命令行三个参数


分别是返回地址
argc 后面argv 字符型指针数组的总个数
argv 字符型指针数组
envp 环境变量
以下是argv的全路径
