C语言限定符

本文介绍了C语言中的三种限定符:const、volatile和restrict。const用于定义只读变量,可以修饰指针本身或指针所指对象;volatile提示编译器变量可能会被外部因素改变,避免编译器优化;restrict保证指针不会通过其他途径访问同一内存,提升效率。这些概念在嵌入式编程和系统级编程中尤其重要。
摘要由CSDN通过智能技术生成

C语言限定符

C语言的限定符包括const、volatile、restrict

在这里插入图片描述

一、const

1、const修饰基础类型

例如:

	const int a = 10;
	a = 100;//此句在c语言中会报错,assignment of read-only variable 'a'
			//a是一个只读变量

2、const修饰指针

const修饰指针有两种情况,一种是修饰指针,指不能改变指针的指向即常指针,数组名就是一个常指针,指向数组的第一个存储空间。

例如:

	int a = 10, b = 20;
	int* const p = &a;
	p = &b;//此句报错,assignment of read-only variable 'p'
			//p是一个只读变量

另一种情况是修饰指针指向的变量,指不能通过指针改变指针所指向的对象。

例如:

	int a = 10, b = 20;
	const int* p = &b;
	p = &a;//此句可以正常运行,即可以改变指针指向
	a = 20;//此句可以正常运行,即可以通过变量名来修改本身的值
	*p = 30;//此句报错,assignment of read-only location '* p'
			//不可通过指针改变指针所指向的对象

但是以上都是将int连在一起表示,如果将const写在int****中间呢?我们来看下面代码

	int a = 10, b=20;
	int const * p = &a;
	p = &b;
	*p = 30;//此句报错,[Error] assignment of read-only location '* p'
			//不可通过指针改变指针所指向的对象

可见int const * pconst int* p等价。const在谁前面就修饰谁,这只是一种记忆方法。

	int* const p = &a;//在这里,const 位于p前面,即修饰p,p是一个常指针
	const int* p = &b;//在这里,const 位于int*前面,它的类型是指向一个具有const限定符的int类型的指针
	int const * p;//在这里,const位于*前面, *并不是一个类型,故把const提前变成const int* p

题外话1:

查看<string.h>头文件会发现里面的函数声明在传入一个固定的字符串时几乎都加了const修饰,这是为了不在函数中不小心的修改指针所指向的内容。

题外话2:

在以下语句中

    char *cp;
    const char *ccp;
    ccp = cp;
    cp = ccp;//这是非法的

这是合法的,并且在大部分的字符串库函数中都是这么使用的。他符合约束条件:两个操作数都是指针有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须具有右边指针所指向类型的全部限定符也就是说无限定符的操作数可以给有限定符的操作数赋值。

左操作数是一个指向有const限定符的char的指针;

右操作数是一个指向没有限定符的char的指针;

char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指向类型的限定符(无),再加上自身的个限定符(const)。(左操作数的限定程度要大于等于右操作数)相反的话若cp = cpp则会报错。

来看以下语句

foo(const char **p){}

int main(int argc,const char **argv){
    foo(argv);
}

//编译报错:argument is incompatible with prototype
//参数与原型不匹配

这是为什么呢?首先我们要了解const char argv。constchar argv是一个没有限定符的指针类型。他的类型是指向有const限定符的char类型的指针的指针。char ****** p是指向**char ***,const char **p 指向的是const char *。**不符合约束条件:每个实参都应该具有自己的类型,这样它的值就可以赋值给与它所对应的形参类型的对象(该对象的类型不能包含有限定符)。

	char *p;
	const char *q;
	q = p;//实际上这个代码是可行的,也就是说char* 和const char* 是相容的,但是这并不意味着char** 和const char**可以相容

二、volatile

volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改。volatile 提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,都会直接从变量地址中读取数据。如果没有 volatile 关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。所以遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问
在这里插入图片描述

例如在stm32GPIO寄存器中每个寄存器被设置为IO类型而IO类型是由宏定义实现的#define __IO volatile

三、restrick

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值