美文网首页
C语言- 指针用法

C语言- 指针用法

作者: 我阿郑 | 来源:发表于2021-12-11 12:25 被阅读0次

    如何表示地址?

    地址是整数,是否可以用int?
    理论上可以,但是为了强调它是个内存地址,提出一些新的类型:

    char* :表示一个char类型变量的地址
    short* :表示一个short类型变量的地址
    int* :表示一个int类型变量的地址
    float* :表示一个float类型变量的地址
    double* :表示一个double类型变量的地址
    unsigned char* :表示一个unsigned char类型变量的地址
    XXX* : 表示XXX类型变量的地址
    

    上面的指针都是基本数据类型的指针
    基本类型指针就是指:存放基本数据类型地址的指针

    int *p;
    int i = 3;
    p = &i;
    
    int j;
    j = *p;
    
    
    • int *p; 中p是变量的名字,p是一个指针变量
    • int * 可以理解为是数据类型;int * 表示变量p存放的是int类型变量的【地址】
    • &i 表示取i的地址,然后赋值给指针变量p,所以变量p保存了i的地址,因此p指向了i,所以通过指针变量p就可以找到i;
    • *p就完全等同于i (或理解为:在所有出现*p的地方都可以替换成i,在所有出现i的地方都可以替换成*p
    • pi是两个不同的变量,并且他们的数据类型也不一样

    关于指针

    • 1- 不同类型的指针,不能互相赋值
    int a = 10;
    int* pa = &a; 
    double* pd = pa; // Error ❌ 左侧double* ,右侧int* , 不能互相赋值
    
    char a = 78;
    float* p = &a; // Error ❌ 左侧float* ,右侧cahr* , 不能互相赋值
    
    • 2- 星号*的位置

    以下几种方式均可以,没有区别, 看个人习惯

    int* p;
    int * p;
    int *p;
    

    星号操作:按地址访问

    有一个指针变量p, 则p用于访问p指向的变量*(p指向的内存)。

    int a = 0x123;
    int *p = &a; // p指向a所在的内存
    *p += 2;
    
    int b = *p;  // 取得p指向内存的值
    int c = *p + 2;
    
    

    指针作为函数的参数

    可以把指针作为函数的参数

    void test(int *p) {
        // 能把指针干什么呢?
        // 使用星号操作*p,来读写内存
        *p = 10;
    }
    
    int main() {
        int a = 0;
        test(&a);
        print("a=%d",a); // 打印10
    }
    
    

    使用指针作为参数,可以实现两种功能:

    • 可以读取上一层函数中变量的值 *p
    • 可以修改上一层函数中变量的值 *p (普通的参数无法实现)
    例: 交换两个变量的值
    void swap(int* a, int* b)
    {
        int t = *a;
        *a = *b;
        *b = t;
    }
    int main()
    {
        int a=10, b=11;
        swap(&a, &b);
        return 0;
    }
    

    传递数组作为参数

    之前说过数组名,实质就是指针类型,传递数组,就是传递指针

    int test(int *p, int length) {
        int sum = 0;
        for(int i=0; i<length; i++) {
            sum += p[i];
        }
        return sum;
    }
    
    int main() {
        int arr[] = {1, 2, 3, 4};
        int ret;
        
        ret = test(arr,4); // 从arr[0] 到 arr[3] 结果sum=10
        ret = test(arr,3); // 从arr[0] 到 arr[2] 结果sum=6
        ret = test(arr + 1,3); // 从arr[1] 到 arr[3] 结果sum=9
        
    }
    
    

    ❤️ 对于test函数来说,不关心传进来的是不是数组;在它眼里,它只是接收到一个内存地址而已

    • 以下两种方法完全等价
    int test(int *p, int length)
    和
    int test(int p[], int length)
    
    • 传递数组时,总是要传递长度信息,不能只把手地址传递给函数,这样是不够的

    传指针有什么作用?

    把一个指针传给函数,有什么作用?

    • 返回多个参数: return只能返回一个值,如果一个函数要返回多个值,必须使用指针参数(输出参数)
    • 效率问题: 传值和传地址,后者一般效率更高

    如何安全的使用指针 ?

    指针不可乱用,安全的使用指针,需要对指针有足够清晰的认识。
    在使用指针之前,一定要弄清楚两个问题:

    • 这个指针指向了哪儿?
    • 这个指针指向的那个地方是否有效?(即:是否能够访问)

    指针指向了哪儿?

    • 指向了变量、数组、结构体
    • 指向0

    指向0的情况:(空指针

    int* p = 0; // 空指针

    空指针

    值为0的指针,称为空指针

    int* p = 0;
    
    当指针为空时,不能使用星号操作。
    int* p = 0;
    printf(“%d \n”, *p); // 不能这么干❌
    
    但空指针是程序员可以接受的一种情况,只需加一个if判断就能解决!
    if(p) {
        printf(“%d \n”, *p);
    } 
    

    空指针:应用

    某些参数可以省,当不想传入时就传一个空指针

    void max_min(const int* arr, int len,
                    int* pmax, int* pmin)
    {
        ...
        if(pmax) *pmax = _max;
        if(pmin) *pin = _min;
    }
    // 调用时
    int _max;
    // 表示只需要得到最大值
    max_min(arr,4, &_max, 0); 
    

    危险的情况

    int* p;
    printf("%d", *p); // 立即crash
    

    这个指针指向哪了? 当一个指针未赋值时,其值为随机值,此时指向了一个随机的内存地址,称为“野指针”

    安全使用指针

    1-杜绝野指针

    一个好习惯:初始化为空指针 : int * p = 0;

    考虑:为什么传递一个空指针是允许的?而传一个野指针是不允许的? (空指针也会崩溃)

    int *  p = 0;
    printf(“ %d  \n”, *p); // 空指针也会崩溃 ❌
    

    传递空指针:函数内部是有办法处理,判断一下就行。
    传递野指针:函数内无法判断出来你是个野指针!!

    void test(int* p)
    {
      // 在使用指针前判断
        if( p != 0)
        {
             printf(“%d \n”, *p);
        }
    }
    

    2-严防数组越界

    当指针指向数组时,要注意不要越界访问

    int arr[4];
    int* p = arr;
    
    p += 4;
    *p = 12; // 已经越界!但不容易察觉!
    

    3-变量是否已经失效?

    如果指向的目标的生命期已经终结(失效),则该指针也失效

    int main()
    {
        int* p = 0;
        if(1)
        {
            int a = 10; // a生效
            p = &a; // p指向a
        } // a已失效
    
        *p = 11; // p指向了一个无效的位置⚠️
        return 0;
    }
    

    所以,指向全局变量的指针,安全性相对较高。因为它的生命期是永恒的,这一块内存总是有效。

    相关文章

      网友评论

          本文标题:C语言- 指针用法

          本文链接:https://www.haomeiwen.com/subject/szxhfrtx.html