5.2 指针(指针与数组)

本文深入探讨了数组与指针的关系,解释了数组名作为指针常量的特性,以及如何通过指针访问和修改数组元素。同时,介绍了泛型指针void*的用法,强调了它在不知道目标类型时的存储地址功能,以及转换和解引用的注意事项。示例代码展示了这些概念的实际运用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

针与数组

        1.数组名本身就是一个指针,代表数组的首元素地址。

        2.对数组元素进行下标访问的本质,就是对数组名和下标做指针计算的结果解引用

                -- arr[i] 等价于 *(arr + i),先算 arr + i ,最后解引用*(arr + i)

                -- &pa[0] => pa + 0 => (pa + 0)

        3.与通常意义上的指针变量不同

                数组名是个指针常量,不能通过再次赋值令其指向其它数据

                int a = 10;

                arr = &a; //不可以!!

                arr++;//不可以!目的是让它指向下一个元素,但arr不可更改!

        关系比较方式:

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

        int *pa = a;

        for(pa = a; pa < a + size; pa++ ) // a+size指向最后一个元素的地址,一开始pa指向的第一个元素的地址肯定小于最后一个元素的地址

        示例:

//数组和指针的那点事儿
#include <stdio.h>
int main(void) {
    int a[5] = {1,2,3,4,5};//定义初始化数组,a表示数组的第1个元素的首地址
    //a++; //a不允许修改
    int *pa = a; //定义初始化指针变量pa来保存数组a的首地址,pa指向a
                //以后通过pa访问数组跟通过a访问数组一模一样,但是pa可以++,a不能++
    int size = sizeof(a)/sizeof(a[0]); //换算数组元个数
    //int size = sizeof(pa)/sizeof(pa[0]); 
    //写法1:
    for(int i = 0; i < size; i++) {
        a[i] = a[i] + 1;
        *(a+i) = *(a + i) + 1;
        pa[i] = pa[i] + 1;
        *(pa+i) = pa[i] + 1;
    }
    for(int i = 0; i < size; i++) {
        printf("%d %d %d %d\n", a[i], *(a+i), pa[i], *(pa+i));
    }
    //写法2:
    for(pa = a; pa < a + size; pa++)
        *pa = *pa + 1;
    for(pa = a; pa < a + size; pa++)
        printf("%d ", *pa); 
    printf("\n");
    return 0;
}

注意!

        int a[4] = {1,2,3,4};

        int *pa = a; //pa指向数组a

        则! a = &a[0] = a + 0 = pa + 0 = &pa[0] = pa++ 不能 a++ !!!

        a[i] = *(a + i) = pa[i] = *(pa + i)

        a[i]本质做两部运算:第一步先算 a + i,先获取第 i 个元素的首地址,第二部做解引用操作: *(a + i)         ,最终获取第i个元素值

        *pa++:先算pa++,结果是pa,然后对pa做解引用,获取指向的内存值,最后让pa+1,指向下一个元素!

        注意!:sizeof(a)/sizeof(a[0]) != sizeof(pa)/sizeof(pa[0]),因为pa始终4/8字节!!!!!

其内存图如下,非常重要!!!!!

 

泛型指针 ----- void* (无类型指针)

        1.仅存储内存地址,不指定目标类型

                例如:void *p = &a; //通过p知道a的类型是什么么?

        2.目标类型不确定,不能直接解引用,*p; //gcc迷茫了

        3.使用前必须先做数据类型转换

        4.泛型指针做指针计算,以1字节为单位

                p = 0x1000;

                p++; //0x001

        范例:

//无类型指针
#include <stdio.h>
int main(void) {
    int a = 100;
    void *p = &a; //定义初始化无类型指针变量p保存a的首地址
    //printf("%d\n", *p); //gcc报错
    //1.间接法:
    int *p1 = (int *)p; //将无类型指针p强转为int类型指针赋值给p1,p1也指向a
    *p1 = 200; //一次性修改4字节内存
    printf("%d\n", *p1); //一次性获取4字节内存
    //2.直接法
    *(int *)p = 200; //先将无类型指针p强转为int类型指针,然后解引用一次性获取4字节数据
                    //然后通过赋值运算符一次性再修改4字节数据
    printf("%d\n", *(int *)p); //一次性获取4字节内存
    //运算
    printf("%p\n", p);
    printf("%p\n", ++p);
    printf("%p\n", ++p);
    printf("%p\n", ++p);
    return 0;
}

         切记:源类型变量在强制转换前后保持不变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值