指针与数组(萌新版)


指针与一维数组

直接看一个例子

int a[3]={1,2,3}, *p;
p = a;//将指针 p 指向数组 a 的第一个元素。
printf("%p %p",a, p);//打印出数组 a 的地址和指针 p 指向的地址。
printf("%d %d %d %d\n", a[0], p[0], *[a+1], *[p+1]);

结果为

0x7ffc70fd5cb0 0x7ffc70fd5cb0
1 1 2 2

a和p地址相同,都能够当成数组名来用,使用起来相似,但两者真的等价吗?

再来看一个例子

int a[3]={1,2,3}, *p;
p = a;//将指针 p 指向数组 a 的第一个元素。
a++;
p++;

这样的运行结果会直接报错

a和p都指向数组的起始地址,但a是地址常量,p是指针变量,a不能修改,而p是可以修改的。
那之前的*[a+1]为什么没报错?这是因为a+1只是进行了计算,并没有对a的值进行修改,而a++则是有赋值的功能。
引申:p++执行后,再次打印p[1],会是什么结果?
其实这个时候p就已经不再指向数组的起始地址了,而是起始地址+1,那么p[1]也就是对应a[2]的位置,写成*(p+1)应该更清晰,有时候不要被下标迷惑了。
Alt

指针与二维数组

假设有这样一个3*2的二维数组

int a[3][2] = {{1,2},{3,4},{5,6}}, *p;

C语言中,二维数组是连续存储的,按行优先存储,用指针p很容易就能直接遍历
在这里插入图片描述
但是,这个时候执行 p = a 的命令则有问题,虽然刚开始都是指向同一起始地址,但是两者格式不同,例如:执行+1操作的话,p是按照元素移动(a[0][0]——>a[0][1]——>a[1][0]),而a是按照行移动(a[0][0]——>a[1][0]——>a[2][0])。

就相当于a[0],a[1],a[2]成为了新的数组名,即一维数组的a。
别被括号干扰了,现在这个a[x]就是一个名!就是一个地址!不是元素了!
在这里插入图片描述
因此,当执行a+1后,就从指向a[0]这个第一行的一维数组变为指向a[1]这个第二行的一维数组,把a称为行地址就能够理解了。

符号功能
a行指针
a[ ]列指针
a[ ][ ]元素值

尝试理解一下这个程序

#include <stdio.h>
int main() {
    int a[3][2] = {{1,2}, {3,4}, {5,6}};
    printf("%p %p %d\n", a,a[1],a[0][1]); //输出数组 a 的地址、数组 a 的第二行的地址、数组 a 的第一行的第二个元素的值。
    printf("%p\n", *(a + 1));//输出数组 a 中第二行的地址。
    printf("%d\n", *(a[1] + 1)); //数组 a 中第二行的第二个元素的值。
    return 0;
}

结果如下

0x7ffd2aabf0f0 0x7ffd2aabf0f8 2
0x7ffd2aabf0f8
4

注意观察数据类型,分清哪些是地址,哪些是元素数值


  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值