我参加嵌入式软件开发的笔试时,经常会遇到直接或者间接考察对C语言中一些关键字含义的理解,所以今天我就简单的总结一下。
(1)保持变量持久。在函数体内,一个被声明为静态变量的变量,在这个变量被调用的过程中保持其实上次调用后的值,并不会被初始化。该变量在程序开始运行时就被初始化,也是唯一的一次初始化。其存储在全局存储区。
file1.c
#include <stdio.h>
int prt_var()
{
int a = 0;
static int b = 0;
printf("a = %d b = %d\n",a++,b++);
return 0;
}
file2.c
#include <stdio.h>
int main()
{
int i;
for(i = 0;i < 5;i++)
prt_var();
return 0;
}
编译后的结果如下
(2)隐藏变量。在一个模块内,一个被声明为静态的变量,只能被文件的函数使用。这样做可防止其他模块因变量同名而访问到该变量,出现访问错误;其存储在全局存储区。
(3)隐藏函数。在模块内,被声明为静态的函数,就意味着该函数只能被该模块内的函数调用。其理由月(2)中相似。
(4)默认初始化为0。如果静态局部变量声明时未被初始化,那么就会被默认初始化为零;在定义一个数组是免去了初始化数组为0的麻烦。例如:static char str[5];
详细解释见:http://blog.csdn.net/keyeagle/article/details/6708077
在做嵌入式开发中volatile是一个经常被用到的关键字,其是32个C语言限定词中的一个,属于类型限定符。
作用:正如其中文意思“易变的”,改变是用来声明一个变量是容易发生变化的,编译是告诉编译器每次都要到内存中去访问该变量,防止编译器过度优化。
用途:
(1)宏定义一个并行设备的硬件寄存器。(嵌入式编程中常用到)
例如:#define GPBCON (volatile unsigned long*)0x56000010
//mini2440中声明led一个控制寄存器
(2)中断子服务程序中会访问到的非自动变量。
例如:volatile unsigned int timer_cnt = 0;
//在一个中断服务程序中进行软件计时
(3)多线程任务中被几个线程共享的变量。
注意:此处的编译器优化的含义
在一个计算机中,访问速度又快到慢依次为:cpu寄存器>cpu内置缓存>内存>硬盘>其他外部存储设备(USB、串口等),为了提高程序的运行速度,编译器会把一些变量拷贝到寄存器中,程序访问该变量时,就直接从寄存器中拷贝到内存中(因为数据大部分存放于栈),而数据状态改变是在内存中发生变化,寄存器中的数据未发生变化,由此导致下次访问的数据不是你想要访问的数据结果。这就是为什么要防止编译器过度优化的原因。加上volatile关键字后,每次都从内存中访问,每次访问到的数据也就是数据的最新状态。
3.关键字inline
在linux内核源码中经常会见到关键字inline,该关键字用于定义内联函数。
优点:
1.对于一些比较短小的函数代码,使用inline可以直接将函数嵌入到代码中,这样做减小系统资源开销。
缺点:
1.inline定义的函数不一定都会被嵌入到代码中。
2.当我们过度使用inline函数,会造成程序文件变大,性能降低。程序文件变大是肯定的,但为什么性能会降低呢?现在的CPU上都有cache,短小的代码在chache中保存的时间更长,这样cache命中的机会更高。其次,如果函数经常别调用的话,就会被长期保存在cache中,而一旦被嵌入到函数中,就失去了调用的机会,换句话说也就是保存在cache中的机会就会大大减小。
inline与宏定义的区别:调用inline时会进行类型检查,而宏定义是没有类型检查的。
inline应用实例:
#include <stdio.h>
void inline temp(int a,int b)
{
a = a^b;
b = a^b;
a = a^b;
printf("a=%d b=%d\n",a,b);
}
int main()
{
int a = 1;
int b = 2;
temp(a,b);
return 0;
}