C语言常用、易错关键词笔记

static

C语言中static可以修饰局部变量、全局变量、指针。

1、 修饰局部变量,即在函数体中,该变量在这一函数被调用过程中不会重新对该变量赋值,会维持上一次的值保持不变。
2、 修饰全局变量时,该变量只能被所在源文件内部所用函数访问,不能被其他文件访问。它是一个本地的全局变量。
3、修饰函数时,该函数只能被所在源文件内部的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

extern

声明外部符号
如果想用来自其他文件(外部文件)的全局变量,要先声明一下。

typedef 和 #define

typedef:类型重定义

例:

typedef unsigned int uint;        //为unsigned int 取一个别名为uint

#define:定义常量和宏

例:

#define P 777          //宏定义777为P

二者的区别:

(1)原理不同

#define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。

typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。

(2)功能不同

typedef用来定义类型的别名,起到类型易于记忆的功能。另一个功能是定义机器无关的类型。如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL, 在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的,typedef float REAL

#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

(3)作用域不同

#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。

(4)对指针的操作不同
例如:

typedef  int* INTPTR1; 

#define INTPTR2 int*

INTPTR1 a,b;        //相当于(int*) a, b ;       a和b都是一个返回值为int的指针

INTPTR2 a,b;        //相当于int  (*a),b;        a是指针,b不是

const

 1、对变量声明只读特性,保护变量值以防被修改。

 2、节省空间,避免不必要的内存分配。const修饰的变量在程序运行过程中只有一份拷贝。

 3、提高程序运行效率。编译器不为普通const常量分配存储空间,而是将他们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储和读取内存的操作。
易错:

const int a;        
int const a;               //以上两者作用一样,表示a是一个常整型数
const int *a;             //a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)
int * const a;            //a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)
int const * a const;   //a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)

volatile

        volatile 声明类型变量的时候,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问;如果不使用 volatile 进行声明,则编译器将对所声明的语句进行优化。即 volatile 关键字影响编译器编译的结果,用 volatile 声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错。 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

为什么影响编译器优化?

        当使用 volatile 声明变量值的时候,编译器总是重新从它所在的原内存读取数据,即使它前面的指令刚刚从该处读取过数据。 用 volatile 定义的变量会在程序外被改变,每次都必须从内存中读取,而不能重复使用放在cache(高速缓存)或寄存器中的备份。

什么情况下使用 volatile?

一般说来,volatile用在如下的几个地方:

一、 中断服务程序中修改的供其它程序检测的变量需要加 volatile ;

二、多任务环境下各任务间共享的标志 应该加 volatile;

三、 存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能有不同意义;

详细介绍请访问:(3条消息) C语言中volatile关键字用法_飞狼说的博客-CSDN博客_c语言volatile关键字

struct  和  union

struct表示的是一种结构体,结构体是一种构造类型,它是由若干个成员组成。其成员可以是一个基本类型数据,也可以是一个构造体类型。struct是声明结构体变量或函数。

union也被称为共同体。union 维护足够的空间来放置多个数据成员中的 ”一种”,而不是为每个数据成员配置空间。在union中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址。声明共用体(联合)数据类型。

 二者区别:

1.在存储多个成员信息时,编译器会自动给struct的每个成员分配存储空间,所以struct 可以存储多个成员信息,而Union每个成员会用同一个存储空间,只能存储最后一个成员的信息。

2.都是由多个不同的数据类型成员组成,但在任何同一时刻,Union只存放了一个被先选中的成员,而结构体的所有成员都存在。

3.对于Union的不同成员赋值,将会对其他成员重写,原来成员的值就不存在了,而对于struct 的不同成员赋值 是互不影响的。

注:在很多地方需要对结构体的成员变量进行修改。只是部分成员变量,那么就不能用联合体Union,因为Union的所有成员变量占一个内存。eg:在链表中对个别数值域进行赋值就必须用struct。

实例说明:

struct 简单来说就是一些相互关联的元素的集合,说是集合,其实它们在内存中的存放是有先后顺序的,并且每个元素都有自己的内存空间。那么按照什么顺序存放的呢?其实就是按你声明的变量顺序来存放的,下面先看一个例子:

struct sTest

{

int a;  //sizeof(int) = 4

char b;  //sizeof(char) = 1

shot c; //sizeof(shot) = 2

}x;

所以在内存中至少占用 4+1+2 = 7 byte。然而实际中占用的内存并不是7 byte,这就涉及到了字节对齐方式。

union 的不同之处就在于,它所有的元素共享同一内存单元,且分配给union的内存size 由类型最大的元素 size 来确定,如下的内存就为一个double 类型 size :

union uTest

{

int a;   //sizeof(int) = 4

double b;  //sizeof(double) = 8

char c;  //sizeof(char) = 1

}x;

所以分配的内存 size 就是8 byte。

既然是内存共享,理所当然地,它不能同时存放多个成员的值,而只能存放其中的一个值,就是最后赋予它的值,如:

x.a = 3; x.b = 4.5; x.c = ‘A’;

这样你只看到x.c = ‘A’,而其它已经被覆盖掉,失去了意义。

详细介绍请访问:(3条消息) Struct 和 Union区别_firefly_2002的博客-CSDN博客_union和struct的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十九-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值