【嵌入式C语言】指针修饰符


视频资源

【嵌入式C语言】 【精准空降到 11:22】 https://www.bilibili.com/video/BV1RW411G7cr/?p=29&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=682
视频传送门


指针+修饰符

const

默认使用的char *或者int *这样的指针类型是可以修改内容的

为了限制这样修改内容的操作,所以C语言又加了一些修饰符,便于程序员之间的沟通~

  • const称之为常量、只读类型的关键字【不能变】

我们可以用const修饰指针变量,如下所示,有很多种方式

#include <stdio.h>

typedef char *pchar;
int main()
{
    printf("Code Begin\n");

    // 一个字节、只读方式
    // 1 == 2
    const char *p1 = NULL; // 1 【建议】
    char const *p2 = NULL; // 2 【不建议】

    // 3 == 4
    char *const p3 = NULL; // 3 【建议】
    char *p4 const = NULL; // 4 【不建议】

    const char *const *p5 = NULL;

    printf("Code End\n");
    return 0;
}

const char * 指针常量

  • 指针常量是指向一个常量的指针。这意味着通过这个指针不能修改它所指向的数据,但是指针本身可以改变,也就是说可以将其指向另一个地址。

那我们现在定义一个const char *p1 = NULL;
怎么分析这个p1呢?

  • 先看核心节点p1,再看左边有个*,说明p1是个指针类型的变量,什么类型呢?再看左边,哦~是char *类型的指针,这个指针的指向位置是可以任意变的,内容也是可以修改的,再往左看,多了个const修饰,意思就是,指向的内存地址可以改变,但是只能读取,不能修改!!!

  • 理论上是这样,只读不能修改!但是这是个建议字符,如果要强制修改的话,也是有方法进行修改内容的。

  • 我们认为const修饰的内容不能变即可

我们就可以把const char *类型的变量理解成一个字符串,就理解成双引号定义的字符串常量。

在这里插入图片描述

在这个例子中,*p 是不可更改的(即不能通过 p 来改变它所指向的值),但是你可以改变 p 使其指向其他的整数变量。

char *const 常量指针

  • 常量指针是一个指针,一旦初始化后,就不能再改变它所指向的地址,但是可以通过这个指针来修改它所指向的数据(除非该数据本身被声明为常量)。

注意这个变量是 char *const p

先看const p,这样定义的是p不可变,指向位置是不变的,不能就是

在这里插入图片描述

在这个例子中,p 必须始终指向在初始化时指定的同一位置,但是如果你不使用 const 修饰 *p,你仍然可以改变 *p 的值。

  • 这种类型,在单片机嵌入式领域一般用作硬件资源的定义,比如说LCD,或者显卡

总结

  • 指针常量:指针可变,内容不变
  • 常量指针:指针不变,内容可变

理解这两者之间的区别对于正确使用C/C++中的指针非常重要,尤其是在需要确保某些数据不会被意外修改的情况下。

CPU与缓存之间的数据传输一样,就比如CPU去访问LCD的一个固定的地址,然后这个地址的内容是不断进行刷新的,屏幕上显示的内容就是不断刷新的

在这里插入图片描述

const char *const *

指向内容不能变,指向地址也不能变。

  • 一般用于ROM

const举例

代码

#include <stdio.h>

typedef char *pchar;
int main()
{
    printf("Code Begin\n");

    const unsigned char *p1 = "hello world!"; // 双引号是什么,在内存的表现形式是什么?就是在内存空间中展开每一个字符
    printf("the one is 0x%x\n", *p1);
    printf("ASCII 'h' is 0x%x\n", 'h'); //'h'是字符,在内存中是ASCII码,也就是一个整数

    *p1 = 'a'; // 修改  //这里出现了段错误,指针指向的内容被非法访问了
    printf("changed string is %s\n", p1);
    printf("Code End\n");
    return 0;
}

终端输出:

在这里插入图片描述

把const去掉,其实是发生了段错误,指针指向的内容被非法访问了
在这里插入图片描述

  • 双引号是整形常量,是不能变的,不能被写,在操作系统中,如果要改变这个内容,就是非法的,产生段错误
  • Segmentation fault

我们看看这两种定义方式有什么不同

const unsigned char *p1 = "hello world!"; 
char buf[] = {"hello world!"};

在这里插入图片描述
char *指向的是某一的,不能修改
数组buf就是连续的空间,是可变的,可以修改

#include <stdio.h>

typedef char *pchar;
int main()
{
    printf("Code Begin\n");

    const unsigned char *p1 = "hello world!"; // 双引号是什么,在内存的表现形式是什么?就是在内存空间中展开每一个字符

    char buf[] = {"hello world!"};
    printf(buf);
    printf(" string is %s\n", buf);
    char *p2 = buf;
    *p2 = 'H';	//第一个字符修改成大写H
    printf("changed string is %s\n", p2);
    printf("Code End\n");
    return 0;
}

输出

PS E:\CProject> cd 'e:\CProject\output'
PS E:\CProject\output> & .\'pointer_const.exe'
Code Begin
hello world! string is hello world!
changed string is Hello world!
Code End
PS E:\CProject\output> 

这样就没有问题了,第一个字符修改成大写H

const内存属性

  1. 内存操作的大小
  2. 内存的变化性,可读可写

man 3 printf

在linux下有个printf的手册
在终端输入man 3 printf就能看到

在这里插入图片描述

volatile

  • volatile防止优化指向内存地址,对指针指向内容的修饰

volatile char *p;

typedef

typedef char *name_t; // name_t是一个指针类型的名称,指向了一个char类型的内存空间
name_t abc;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北国无红豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值