zoukankan      html  css  js  c++  java
  • C指针本质探究

    • 指针是什么

    我的解释是,把内存看成能容纳东西的房间。这个房间的大小是一个字节(8位)。房间可以容纳东西(内容),房间有自己的门牌号(地址)。

    例如:

    int a = 5;

    我们申请了一个名为a的房间,这个房间一共由四个基本房间组成(32位),这个房间里存放的内容为5,那它的门牌号呢?c语言不需要我们直接接触地址,如果学过汇编就很清楚这个问题了,c中我们可以用 &a 取得a的地址,即这个房间的门牌号。

    指针

    上面是示意图,能类比内存的模样。如果我们认为第六个房间里放的是门牌号,那么它指向的是一号房间。

    我们定义  

    int *p = &a;

    这时候p这个房间里面就存放了a的门牌号,注意p自己也是房间,也有门牌号。

    因为不论何种类型的指针存放的都是地址,所以其所需的房间大小都是一样的。

    • 指针类型的作用

    定义一个指针变量,我们需要这样做:

    int *p;

    前面提到所有类型的指针所需的空间都是一样大的,为什么指针需要分类型?

    我们这样访问指针:

    int b = *p;

    访问的时候出了需要知道目标房间的门牌号,还要知道由多少间基本房间(字节)组成。char类型占一个基本房间,int类型占4个基本房间(32位),自定义的类型也许更多。所以访问的时候仅仅知道房间的门牌号还是不够的,还需要知道其大小。我们用*p的时候,编译器需要知道我们要从其地址开始读几个字节的数据,所以我们需要定义指针的类型。

    例:

    #include <stdio.h>
    #include <stdlib.h> 
    
    struct TY
    {
        char s[100];
    }; 
    
    int main()
    {
        int *pa = 0x0;
        char *pb = 0x0;
        TY *pc = 0x0; 
    
        ++pa;
        ++pb;
        ++pc; 
    
        printf("%d   %d\n",pa,sizeof(int));
        printf("%d   %d\n",pb,sizeof(char));
        printf("%d   %d\n",pc,sizeof(TY));
        return 0;
    }

    void *类型指针加大了c指针的灵活性。我的上一篇博文《void*指针实现支持所有数据类型的容器》,就是用void*实现的,在计算偏移地址的时候,我把void*强制转换成char*,这样每次++就会移动一个字节。

    • 指针的作用

    指针很灵活,不仅能够访问数据,还能访问函数。

    如果有汇编基础,就知道在内存里数据和代码是没有区别的。所以指针能够指向数据,也就能够指向函数代码入口。

    用指针访问数组,传递参数,访问某个特定地址,有用的地方很多

    • 指针的潜在风险

    c中的指针是允许强制转换类型的。如

    int *a;
    
    char c;
    
    a = (int*)&c;

    这样是允许的,但是有什么风险?

    结合上面说的,指针类型制定了其访问的长度。如果按上面那样做,再有这样的句子:

    *a = ‘c’;

    它修改的就不仅是c的哪一个字节了,而是四个字节。虽然执行

    printf(“%c\n”,c)

    输出的是c。那是因为小端机的原因,结果没错,但是把后面三个不属于c的字节给写了,越界访问呐。

    还有指针悬空,内存泄露等问题。所以用指针时候需要注意。

  • 相关阅读:
    C++类继承内存布局(二)
    C++类继承内存布局(一)
    排序算法
    python 文件路径问题
    python map对象
    python reduce() 函数
    python eval 用法
    PyCharm引入自定义类报错
    Python中的lambda的简单介绍
    python time模块和datetime模块
  • 原文地址:https://www.cnblogs.com/nanshu/p/2792028.html
Copyright © 2011-2022 走看看