关于C语言的类型修饰符

分享网址

http://wenku.baidu.com/link?url=e-xWNn7f84rrEf_vhHz5CQh2LCVmaGBTA6iB0BC8zPv_8eXz5SKmRofsSuenh8wn_JjeQZBD103xCA6wqDkYo9SzlIvKgCpYwwrbyNvbxVS

在一般的

C

教科书中,可以见到

6

种类型修饰符,分别是

: auto, const, register,

static, volatile, extern.

局部变量除非显式指明为

static,

否则默认为

auto

,所以一般不会在代码中使用类型

修饰符

auto.

在后编译器时代,优化器可以合理的分配寄存器,所以一般不会在代码中使用类型修

饰符

register.

extern

只用于声明全局变量,用法单一。

本节将主要介绍

const, static

volatile.

1. const

首先需要注意的是,

const

修饰的是在它前面的类型,如果它前面没有类型,那它修

饰的是紧跟着它的那个类型。

例如:

(a)const int i = 0;

(b)int const i = 0;

是完全一样的。

(a)

中,

const

前面没有类型,它就修饰它后面的那个

int

类型。在

(b)

中,

const

修饰它前

面的

int

类型,两者没有任何区别。

再看另一个稍复杂一点的例子,下面两条语句却不相同:

(c)const int *pi = 0;

/*

相当于

int const *pi = 0; pi

是一个指向

const int

的指针,复引用此运算符为得到一

const int

的类型,该类型不能作为左值,在该语句后使用类似于

*pi = 1

的操作将导致

编译错误。但该变量本身并不具备

const

属性,可以使用

pi = &i

的操作。可用于访问只读

存储器。

*/

(d)int* const pi = 0;

/* pi

是一个指向

int

类型的

const

指针,复引用此运算符为得到一个

int

类型,该类型可以

作为左值,在该语句可以使用类似于

*pi = 1

的操作,但该变量本身具备

const

属性,使用

pi = &i

的操作将导致编译错误。可用于访问固定位置的存储器。

*/

再看一个更复杂的例子:

(e)const int* const pi = 0;

/* pi

*pi

均不能作为左值。它只适合于读取某个固定位置的只读存储器

*/

const

还有下列典型用法

:

*

用于参数列表,通常修饰的是指针类型,表明该函数不会试图对传入的地址进行写

操作。例如:

void *memcpy(void *, const void *, size_t);

*

用于返回值,通常是一个指向只读区域的指针。例如:

const datatype_t *get_fixed_item(int index);

*

给固定不变的数据

(

例如码表

)

加上只读属性,在某些情况下可以减小

ram

的开销。

2.static

static

用于全局变量声明和局部变量声明具有完全不同的语义,不得不说,这是

C

言设计中的一个不合理之处。当

static

用于修饰全局变量声明

(

或函数声明,可以认为函数

声明就是声明一个指向代码段的指针,该指针的值最后由链接时决定,从这个意义上说,

函数声明也是一种全局变量声明

)

,它表示该变量具有文件作用域,只能被该源文件的代码

引用,不能被其他源文件中的代码访问。在编译时引起的实际变化是被

static

修饰的变量

不会被写入目标文件的输出节,在链接时解析其他模块中的未定义符号时不会被引用到。

它的反义词是

extern

例如:

------main.c---

extern int a(void);

int main(){ return a(); }

------a.c------

/* link will fail unless remove

static

modifier */

static int a(void) { return 0; }

static

用于修饰局部变量声明,它表示该变量不是分配在该函数的活动记录中,而

是分配在全局的数据段

(

bss

)

中。简单的说,就是被

static

修饰的局部变量实际上并不

是局部变量,而是具有函数作用域的全局变量,除了只能在定义它的函数内访问外

(

这是由

C

语法决定的

)

,它的运行时特征和全局变量完全一样,函数返回不会影响它的状态,它的

初始化仅有一次,发生在程序的装载时,而不是在每次函数调用的时候初始化。它的反义

词是

auto

例如

,

下面这段函数返回自己被调用了多少次:

int callee(void) {

static int times_called = 0;

return (++ times_called);

}

3.volatile

volatile

修饰符的作用是告诉优化器不能优化这个变量的读写操作,一定要为这个变

量的读写操作生成代码。

例如:

/*

延时操作

*/

int foo(void) {

/* 100

次减法后返回

*/

volatile int i = 100; /*(a)*/

while (i > 0) i--;  /*(b)*/

return 0;

}

在无

volatile

修饰的情况下,因为变量

i

的变化对上下文无影响,所以优化器很可能

会省略掉对

i

操作的代码,而只生成

return 0

的代码,加上

volatile

可以保证编译器一定为

语句

(a)

(b)

生成代码,达到延时的目的。

/*

设备状态判定

*/

int uart_write_char(int c) {

/*

向串口发送寄存器写入待发送字符

*/

*(volatile unsigned int *)UART_TX_REG = c;

/*

判断是否已发送

*/

while ( (*(volatile unsigned int *)UART_STATUS_REG & TX_BIT) != 0); /*(c)*/

return 0;

}

在语句

(c)

中,如果不使用

volatile

,优化器可能会因为在两次读取

UART_STATUS_RE

G

之间没有对

UART_STATUS_REG

的写操作而将读取操作外提到循环体外而导致死循环。

时间: 2024-08-28 05:06:25

关于C语言的类型修饰符的相关文章

c语言类型修饰符及内存

太难了,嵌入式这条路是个大坑啊,学的东西太多,但没办法,既然选择了这条路,坚持走下去吧,打好基础,铺好每一块砖,才能走的更加稳健 今天来学习一下c语言类型修饰符及内存分布 1.auto int a; 默认在内存 2.register int a; 限制变量定义在寄存器上的修饰符 编译器会尽量安排CPU的寄存器去存放这个a,如果寄存器不足,a还是放在内存中 取地址符号&对a不起作用 3.static 应用场景: 1.函数内的变量 2.函数外的变量 3.函数的修饰符(函数也是一个变量) int fu

C语言学习笔记(2):volatile与register类型修饰符

1.volatile volatile是易变的,不稳定的意思,volatile是关键字,是一种类型修饰符,用它修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统.硬件或者其他线程等,遇到这个关键字声明的变量,编译器对访问该变量的代码不在进行优化,从而可以提供对特殊地址的稳定访问.那么什么是编译器优化呢? 为了提高运行效率,攻城湿们可是费尽心机地把代码优化,把程序运行时存取速度优化.一般,分为硬件优化和软件优化.硬件优化,流水线工作,详细可以参考<计算机组成原理>.软件优化,一部分是程序

C++变量内存分配及类型修饰符

前言 了解C++程序内存分配,有助于深刻理解变量的初始化值以及其生存周期.另外,变量类型修饰符也会影响到变量的初始化值及其生存周期.掌握了不同类型变量的初始化值及其生存周期,能够让我们设计程序时定义变量时更准确. 内存分配 1.     C++程序的内存布局 现代电脑都是遵循冯诺依曼体系结构,所以C++程序的内存布局也是遵循该体系的.主要包括5个部分,即代码段.数据段.BSS段.堆和栈.. 1.     代码段 代码段(code segment/text segment),通常是指用来存放程序执

功能:类型修饰符long和unsigned的使用

#include<stdio.h> main() { char a1,b1; unsigned char a2,b2; int x1,y1; long x2,y2; a1=127;    b1=129; a2=127;    b2=129; x1=32767;   y1=32769; x2=32767;   y2=32769; printf("a1=%d,a2=%u,b1=%d,b2=%u\n",a1,a2,b1,b2); printf("x1=%d,x2=%u,

Java语言中的修饰符

类.方法.成员变量和局部变量的可用修饰符 修饰符 类 成员方法 构造方法 成员变量 局部变量 abstract Y Y _ _ _ static _ Y _ Y _ public Y Y Y Y _ protected _ Y Y Y _ private _ Y Y Y _ synchronized _ Y _ _ _ native _ Y _ _ _ transient _ _ _ Y _ volatile _ _ _ Y _ final Y Y _ Y Y 1.访问控制修饰符: Java语言

Java面向对象编程之Java语言中的修饰符

近日,读了孙卫琴老师的<Java面向对象编程>一书,心中颇有些感悟,想着将其记录下来. Java中的修饰符 在Java语言中,有这样一些单词(说得再准确点儿,应该是形容词):abstract(抽象的).static(静态的).public(公共的).protected(受保护的).private(私有的).synchronized(同步的).native(本地的).transient(暂时的).volatile(易失的)和final(不可改变的),它们被成为修饰符,这些修饰符可以修饰类.变量和

C#语言中的修饰符汇总

1. 访问修饰符 指定声明的类型和类型成员的可访问性. (1) public:对任何类和成员都公开, 无限制访问;是类型和类型成员的访问修饰符.公共访问是允许的最高访问级别.对访问公共成员没有限制. (2) private:仅仅对该类公开;是一个成员访问修饰符.私有访问是允许的最低访问级别.私有成员只有在声明它们的类和结 构体中才是可访问的. (3) internal:只能值包含该类的程序集中访问该类(只是单独的项目,而不是整个解决方案);是类型和类型成员的访问修饰符.只有在同一程序集的文件中,

C#语言中的修饰符

public:公有访问.不受任何限制. private:私有访问.只限于本类成员访问,子类和实例都不能访问. protected:保护访问.只限于本类和子类访问,实例不能访问. internal:内部访问.只限于本项目(程序集)内访问,其他不能访问. protected internal :内部保护访问.只限于本项目或是本类和子类访问,其他不 能访问 1.类(class)    默认的修饰符:private        可以被修饰的:public,private,internal,protec

关于Java语言中那些修饰符

一.在java中提供的一些修饰符,这些修饰符可以修饰类.变量和方法,在java中常见的修饰符有:abstract(抽象的).static(静态的).public(公共的).protected(受保护的).private(私有的).synchronized(同步的).native(本地的).transient(暂时的).volatile(易失的).final(不可改变的) 二.修饰顶层类的修饰符包括abstract.public和final,而static.protected和private不能修