Chinaunix首页 | 论坛 | 博客
  • 博客访问: 214456
  • 博文数量: 72
  • 博客积分: 3890
  • 博客等级: 中校
  • 技术积分: 810
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-05 20:00
文章分类

全部博文(72)

文章存档

2010年(20)

2009年(52)

我的朋友

分类: LINUX

2009-02-11 09:46:11

C中的关键字

原文地址:http://blog.chinaunix.net/u1/37549/showart_465022.html
一、const修饰符
 
  const意味着"只读"。区别如下代码的功能非常重要,也是老生长谈,如果你还不知道它们的区别,而且已经在程序界摸爬滚打多年,那只能说这是一个悲哀:

const int a;
int const a;
const int *a;
int * const a;
int const * a const;
Const修饰符在C语言中是一个比较新的描述符,意即其所修饰的对象为常量。
说明:
1、必须初始化
const int i=5;  //合法
const int j;  //非法,导致编译错误
{const int j;j=5;} //非法
2、可以通过函数进行初始化
int value();
const int i=value();
3、限定符声明变量只能被读,即其值不可以修改
const int i=5;
int j=0; 
i=j;  //非法,导致编译错误
J=i;  //合法
4、可以在另一个连接文件中引用const常量
extern const int i;  //合法
extern const int j=10; //非法,常量不可以被再次赋值
5、数值常量和指针常量
const int p1  //p1是常量,p1的值不能被修改
const int *p2  //指针p2所指的内容是常量,不能被修改,当p的指向可以被修改。
Const int * const p3 //指针p3是常量,所指内容也是常量
二、Static修饰符
1、用static声明局部变量
该变量为静态局部变量,即该局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元不释放,在下一次该函数用时,该变量已有值,就是上一次函数调用结束时的值.
程序例子:
int fac(int n)
{
    static int f=1;
    f=f*n;
    return(f);
}
int main(int argc,char **argv)
{
    int i;
    for(i=1;i<5;i++)
    {
        Printf("%d!\n",i,fac(i));
    }
}
运行结果:
1!=1
2!=2
3!=6
4!=24
5!=120
2、用static声明外部变量
该变量为静态外部变量,该变量只限于被本文件引用,而不能被其他文件引用。
三、valatie修饰符
volatile修饰符号告诉编译程序不要对该变量所参与的操作进行某些优化。
一般来说,volatile用在如下的几个地方:
1)中断服务程序中修改的供其它程序检测的变量需要加volatile;
2)多任务环境下各任务间贡享的标志应该加volatile;
3)存储器映射的硬件寄存器通常也要加volatile说明,因为每次都它的读写都可能有不同意义;
程序例子:
time_t time_addition(volatile const struct timer *t,int a)
{
    int n;
    int x=0;
    volatile time_t then;
    
    then=t->value;
    for(n=0;n<1000;n++)
    {
        x=x+a;
    }
    return t->value-then;
}

 

C语言编译器会对用户书写的代码进行优化,譬如如下代码:

int a,b,c;
a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/
b = a;
a = inWord (0x100); /*再次读取I/O空间0x100端口的内容存入a变量*/
c = a;

  很可能被编译器优化为:

int a,b,c;
a = inWord(0x100); /*读取I/O空间0x100端口的内容存入a变量*/
b = a;
c = a;

  但是这样的优化结果可能导致错误,如果I/O空间0x100端口的内容在执行第一次读操作后被其它程序写入新值,则其实第2次读操作读出的内容与第一次不同,b和c的值应该不同。在变量a的定义前加上volatile关键字可以防止编译器的类似优化,正确的做法是:

volatile int a;


  volatile变量可能用于如下几种情况:

  (1) 并行设备的硬件寄存器(如:状态寄存器,例中的代码属于此类);

  (2) 一个中断服务子程序中会访问到的非自动变量(也就是全局变量);

  (3) 多线程应用中被几个任务共享的变量。

CPU字长与存储器位宽不一致处理

  在背景篇中提到,本文特意选择了一个与CPU字长不一致的存储芯片,就是为了进行本节的讨论,解决CPU字长与存储器位宽不一致的情况。80186的字长为16,而NVRAM的位宽为8,在这种情况下,我们需要为NVRAM提供读写字节、字的接口,如下:

typedef unsigned char BYTE;
typedef unsigned int WORD;
/* 函数功能:读NVRAM中字节
* 参数:wOffset,读取位置相对NVRAM基地址的偏移
* 返回:读取到的字节值
*/
extern BYTE ReadByteNVRAM(WORD wOffset)
{
 LPBYTE lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */

 return *lpAddr;
}

/* 函数功能:读NVRAM中字
* 参数:wOffset,读取位置相对NVRAM基地址的偏移
* 返回:读取到的字
*/
extern WORD ReadWordNVRAM(WORD wOffset)
{
 WORD wTmp = 0;
 LPBYTE lpAddr;
 /* 读取高位字节 */
 lpAddr = (BYTE*)(NVRAM + wOffset * 2); /* 为什么偏移要×2? */
 wTmp += (*lpAddr)*256;
 /* 读取低位字节 */
 lpAddr = (BYTE*)(NVRAM + (wOffset +1) * 2); /* 为什么偏移要×2? */
 wTmp += *lpAddr;
 return wTmp;
}

/* 函数功能:向NVRAM中写一个字节
*参数:wOffset,写入位置相对NVRAM基地址的偏移
* byData,欲写入的字节
*/
extern void WriteByteNVRAM(WORD wOffset, BYTE byData)


/* 函数功能:向NVRAM中写一个字 */
*参数:wOffset,写入位置相对NVRAM基地址的偏移
* wData,欲写入的字
*/
extern void WriteWordNVRAM(WORD wOffset, WORD wData)
阅读(724) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~