深入理解指针(二)

一、指针变量类型的意义

 指针变量的大小和类型无关,只要是指针变量,在同一个平台下,大小都是一样的,为什么还要有各种各样的指针类型呢?其实指针类型是有特殊意义的,我们接下来继续学习。

1.1指针的解引用

#include<stdio.h>
int main()
{
    int n = 0x11223344;
    int* p1 = &n;
    *p1 = 0;
    return 0;
}

这个代码会将n的4个字节全部改为0。

#include<stdio.h>
int main()
{
    int n = 0x11223344;
    char* pc = (char*)&n;
    *pc = 0;
    return 0;
}

但这个代码只是将n的第一个字节改为0。

结论:指针的类型决定了对指针解引用时一次能操作几个字符。

比如:char*类型的指针解引用就只能访问一个字节,而int*类型的指针解引用就能访问四个字节。

1.2指针+-整数

我们先看一段代码

#include<stdio.h>
int main()
{
    int n = 6;
    char* pa = (char*)&n;
    int* pn = &n;

    printf("%p\n", &n);
    printf("%p\n", pa);
    printf("%p\n", pa+1);
    printf("%p\n", pn);
    printf("%p\n", pn+1);
    return 0;
}

可以看出char*类型的指针变量+1跳过一个字节,int*类型的指针变量+1跳过了4个字节。

1.3void*指针

        在指针类型中有一种特殊的类型是 void* 类型的,可以理解为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进行指针的+-整数和解引用的运算。

例如:

#include<stdio.h>
int main()
{
    int a = 6;
    int* pa = &a;
    char* pc = &a;
    return 0;
}

在上面的代码中,如果将一个int类型的变量的地址赋值给一个char*类型的指针变量,编译器就会给出一个警告,这是因为类型不兼容。但如果使用void*类型,就不会出现这样的问题。

使用void*类型的指针接收地址:

#include<stdio.h>
int main()
{
    int a = 6;
    void* pa = &a;
    void* pc = &a;
    return 0;
}

但还有一个问题,void*类型的指针可以接收不同类型的地址,但无法直接进行指针运算。

#include<stdio.h>
int main()
{
    int a = 6;
    void* pa = &a;
    void* pc = &a;
    *pa = 10;
    *pc = 0;
    return 0;
}

那么,void*类型的指针到底有什么用呢?

        一般void*类型的指针是使用在函数参数部分的,用来接收不同类型的数据地址,在后面我们会讲到。

二、const修饰指针

2.1const修饰变量

        变量是可以修改的,如果把变量的地址交给一个指针变量,通过指针变量的也可以修改这个变量。但是如果我们希望一个变量加上一些限制,不能被修改,怎么做呢?这就是const的作用。

#include<stdio.h>
int mian()
{
    int m = 6;
    m = 9;//m可以被修改
    const int n = 0;
    n = 20;//n不能被修改
}

        上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n进行修改,就不符合语法规则,就报错,致使没法直接修改n。但是如果我们绕过n,使用n的地址,去修改n就能做到了。

#include<stdio.h>
int main()
{
    const int n = 0;
    printf("n=%d\n", n);
    int* p = &n;
    *p = 6;
    printf("n=%d\n", n);
    return 0;
}

        我们可以看到这里一个确实修改了,但是我们还是要思考一下,为什么n要被const修饰呢?不就是为了不能被修改吗,如果p拿到n的地址就能修改n,这样就打破了const的限制,这是不合理的,所以应该让p拿到n的地址也不能修改n,那接下来怎么做呢?

2.2const修饰指针变量

const修饰指针变量,可以放在*的左边和右边,但是意义是不一样的。

第一种情况:const在*的左边:

#include<stdio.h>
int main()
{
    int n = 6;
    int m = 9;
    const int* p = &n;
    *p = 20;//error
    p = &m;
}

const放在*的左边,不能够改变n的值。

第二种情况:const放在*右边的情况:

#include<stdio.h>
int main()
{
    int n = 6;
    int m = 9;
    int* const p = &n;
    *p = 20;
    p = &m;//error
}

const放在*的右边,不能改变指针变量的内容;

第三种情况:*左右两边都有const:

#include<stdio.h>
int main()
{
    int n = 6;
    int m = 9;
    int const* const p = &n;
    *p = 20;//error
    p = &m;//error
}

结论:

        • const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。
但是指针变量本身的内容可变。
        • const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。

  • 26
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值