指针

  • 指针

    核心

    本质上指针就是地址

    概念理解:

    • 内存单元的编号就是地址(指针)

    • 口语中的指针,其实是指针变量是用来存放内存地址的变量

    1
    2
    3
    4
    5
    int main(){
    int a=0;
    int* pa =&a;//pa用于存放a的值 类型为int *
    return 0;
    }

    结论

    • 指针变量 里面存放的是地址,通过这个地址,能够找到一个内存单元

    • 在32位的机器上,有32个地址线,能够编译2的32次方的地址

      • 指针在32位机器上是4个字节
    • 在64位的机器上,有64个地址线,能够编译2的64次方的地址

      • 在64位机器上指针为8个字节

    指针类型

    • 导入
    1
    2
    3
    4
    int a=10;
    int *pc=&a;
    char *pi=&a;
    double *pl=&a;

    在内存中我们知道

    • 指针变量所占的字节大小取决于该机器所配备的位数

    那么思考:

    为什么我们需要为指针设置那么多的类型?而不直接创建一个总的指针来定义?

    实际意义
    1
    2
    3
    4
    int a=0x11223344;//16进制的数字
    int* pc=&a;//指针变量存放地址
    *pc=0;//地址所找到的那个值进行修改为0
    //最终四个字节的位置都被改变为了0
    1
    2
    3
    4
    int a=0x11223344;
    char* pc=(char *)&a;//强制类型转化为字符指针变量
    *pc=0;
    //最终只有一个字节的位置被修改为了0

    如果int*的指针,指针访问4个字节

    如果char*的指针,指针访问1个字节

    结论1

    • 指针类型决定了指针在被解引用时访问几个字节

    • 但是不决定指针变量所占的字节大小

    1
    2
    3
    4
    5
    6
    7
    int a=0x11223344;
    int *pc =&a;
    char* pq =(char*)&a;
    printf("%p",pc);//地址--首元素的地址
    printf("%p",pc+1);//跳过了四个字节的指针步长
    printf("%p",pq);//地址--首元素的地址
    printf("%p",pq+1);//跳过了一个字节的指针步长

    结论2

    • 指针的类型决定了指针+1或 -1操作时,跳过几个字节

    • 决定了指针的步长

    理解

    指针变量的大小与机器位数相关,指针变量指向的那个空间即为内存所决定的大小由它的类型所决定
    指针变量是存储地址的 而它的访问权限取决于该数据变量的类型
    类型有多大 可访问该数据变量的字节也会随之增大


    野指针

    不赋初值
      • 错误演示
    1
    2
    int* p1;//未为指针变量赋初值
    *p1=10;//非法访问指针变量存放的地址对应的值

    ​ 因为p1为指针变量 在内存中有很多块空间 如果不赋初值 会导致指针指向发生错误

    ​ 当不知道给指针赋什么值时 我们采用空指针赋值给指针变量

    1
    2
    3
    4
    int * p=NULL;//赋予空指针
    if(p!=NULL){
    *p=20;
    }//需要判断此指针不为空指针

    这里需要用判断语句 判断该指针是否为空指针 如果不为空指针 才能对指针里的变量进行修改

    指针指向的空间释放
      • 错误演示
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //局部变量的生命周期
    //在所限定的代码块区内部 出了代码块区 则这个局部变量会被销毁
    int *test(){
    int a=10;//a为局部变量
    //在test函数可以使用,但是a出了该函数会被销毁
    return &a;
    }
    int main(){
    int *p=test();
    //指针变量能够找到该变量地址
    //但是不能访问
    return 0;
    }
    指针下标越界
      • 错误演示
    1
    2
    3
    4
    5
    6
    7
    int arr[10]={0};
    int i=0;
    int *p=&arr;//首元素地址
    for(i=0;i<=10;i++){
    *p=i;
    *p++;//此时会发生指针下标越界,访问不到下标为10的值
    }
    结论

    为防止野指针的出现,我们采用以下几点:

    • 对与指针变量赋初值

      • 当然,可以采取赋空指针的方法–防止指针指向错误
    • 注意下标越界问题,思考该数组的元素个数

    • 调用函数使用指针时,避免返回局部变量的地址