C语言指针-----指针与数组

1、指针与一维数组
2、指针与二维数组
3、指针数组与数组指针
指针里面最难的一种就是指针与数组了,对于指针和二维数组来说这里面的关系比较复杂。牵涉到编译器的原理和编译过程。
1、指针与一维数组
指针是指向一个内存的地址,一维数组的数组名代表一块内存(这个数组)的首地址,和数组首元素的地址一样,但数组名不等价与首元素的地址,数组名代表一整块地址,不仅仅是一个元素。指针和数组名都和地址有关系,这两个有什么区别呢?
如果仅仅是使用上来说,数组名不能再被赋别的地址,因为它可以理解为是一个指针常量(指向地址的内容可以修改,指向的地址无法修改),也可以理解为数组名仅仅是一个标号,在编译的过程中,并没有分配内存空间,只存在于符号表里。
除了这些,正常使用时它和指针在使用上就没有区别了。(编译时,编译器不会对指针访问数组越界处理,而通过数组名越界会出错)

#include<stdio.h>
int main(void){

    int a[3]={1,2,3};
    int *ptr=a;
    printf("a size is %d\n",sizeof(a));
    printf("ptr size is %d\n",sizeof(ptr));
    printf("a[0] is %d\n",*a);
    printf("a[1] is %d\n",*(a+1));
    printf("a[1] is %d\n",a[1]);
    printf("a[1] is %d\n",*(ptr+1));
    printf("a[1] is %d\n",ptr[1]);
}

结果
总结:a作为右值时的等同于&a[0],表示数组首元素的地址,而不是数组的首地址,这仅仅是代表,并没有一个地方来存储这个地址,也就是说编译器并没有为数组a分配一块内存来存储其地址,这一点就与指针有很大的差别。但是在对数据的操作上可以认为大致等价。

2、指针与二维数组
说这个复杂,其实也不太复杂,复杂就复杂在这里有二维指针的概念。
同样的,数组名代表二维数组的首地址,是一整块内存的首地址。
访问方式可以是**p *p[i] p[i][j]三种方式这里p同样可以换成数组名
区别和上面差不多,只不过在将二维数组名赋值给指针时,不能采用**p=a这种形式。

#include<stdio.h>
int main(void){

    int a[2][2]={1,2,3,4};
    //int (*ptr)[2]=a;
    int *ptr[2]={a[0],a[1]};
    //int **ptr=(int**)a;//有问题 
    printf("a size is %d\n",sizeof(a));
    printf("ptr size is %d\n",sizeof(ptr));
    printf("a[0] is %d\n",**a);
    printf("a[1] is %d\n",**(a+1));
    printf("a[1] is %d\n",*a[1]);
    printf("a[1] is %d\n",**(ptr+1));
    printf("a[1] is %d\n",*ptr[1]);
}

编译结果

3、指针数组与数组指针
这个也是最容易混淆的概念,当面对的是二维数组是,这两个作用一样,都可以来接收二维数组。
数组指针:存放指针的数组
指针数组:指向数组的指针

#include<stdio.h>
int main(void){

    int a[2][3]={1,2,3,4,5,6};
    int (*ptr)[3]=a;//指针数组 
    //int *ptr[2]={a[0],a[1]};//数组指针 
    printf("a[0] is %d\n",**a);
    printf("a[1] is %d\n",**(a+1));
    printf("a[1] is %d\n",*a[1]);
    printf("a[1] is %d\n",**(ptr+1));
    printf("a[1] is %d\n",*ptr[1]);
}

编译结果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值