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的区别