首页 > 代码库 > 编程珠玑之关键字(1)--《c语言深度剖析》整理(转)

编程珠玑之关键字(1)--《c语言深度剖析》整理(转)

一、最快关键字register

     关键字regiter请求编译器尽可能的将变量存在CPU的寄存器中。有几点注意的地方。

        1、register变量必须是能被CPU寄存器所接受的类型,这通常意味着register变量必须是一个单个的值,并且其长度应小于或等于整型的长度。

    但是,有些机器的寄存器也能存放浮点数。

       2、register变量可能不存放在内存中,所以不能用取址符运算符“ & ”。

       3、只有局部变量和形参可以作为register变量,全局变量不行。

       4、静态变量不能定义为register。

       总结:寄存器变量不是越多越好,当寄存器变量的个数超过寄存器的数目的时候,寄存变量也就退化为放到内存中。因此寄存器变量应用较少。

二、static作用

       1. 修饰变量

       (1) 限定变量的作用域: (存放于文件的静态区中)

         本文件中:

         静态全局变量:作用域从变量定义开始处到文件结束(本文中在定义之前引用此变量也要加extern)

         静态局部变量:作用域限于定义的函数中

         工程文件中: 仅限本文件中,其他的文件的不能引用此变量

      (2) 生命周期:

        从程序启动直至程序结束。

        2. 修饰函数

        限定函数的作用域为本文件中,其他的文件不能引用此函数

三、最容易混淆的关键字sizeof(本人之前一直以为sizeof是函数 惭愧)

       事实证明 sizeof是关键字,如下:

      int i=0;
       A),sizeof(int); B),sizeof(i); C),sizeof  int; D),sizeof  i;

      此处四种用法第三种是错误的 ,由此可见sizeof 是关键字

      关于sizeof的 一些用法习题:

    int *p = NULL;
   sizeof(p)——
   sizeof(*p)——
   int a[100];
   sizeof (a) ——
   sizeof(a[100])——
   sizeof(&a)——
   sizeof(&a[0])——
   int b[100];
   void fun(int b[100])
   {
        sizeof(b);// sizeof (b) ——
   }

 答案: 4   4   400  4   4  4  4

四、 bool, float , 指针类型与零值的比较

   1. bool类型的值与0比较

   A), if(bTestFlag == 0); if(bTestFlag == 1);
   B), if(bTestFlag == TRUE); if(bTestFlag == FLASE);
   C), if(bTestFlag); if(!bTestFlag);

   解析:

    A :可读性比较差,不知道bTestFlag变量的类型,误以为是整形

    B:不同的编译器,true值的定义不同:Visual C++定义为1,而Visual Basic 就把TRUE 定义为-1

    C:规范 编译器中0 为false 非零为true

  2. float 与 0 比较

        float fTestVal = 0.0;
      A), if(fTestVal == 0.0); if(fTestVal != 0.0);
      B), if((fTestVal >= -EPSINON) && (fTestVal <= EPSINON)); //EPSINON 为定义好的精度。

      解析:float 在计算机存储有精度限制,与0,与具体的浮点数直接比较都是不准确的,所以B的定义较好。[0.0-EPSINON,0.0+EPSINON] 当然EPSINON范围不能过大

  3. 指针变量与0 比较

      int* p = NULL;//定义指针一定要同时初始化,指针与数组那章会详细讲解。
    A), if(p == 0); if(p != 0);
    B), if(p); if(!p);
    C) , if(NULL == p); if(NULL != p);
   解析:A  容易和int 类型的想混淆;B 容易和bool类型想混淆(可读性比较差)

五、c语言中的空语句的写法

      1)  ;

      2) NULL;

六、switch 关键字

       switch关键字使用注意事项:

       1) case 后面变量: 整形或字符型或者常量表达式(可以跟const类型修饰的变量,比如const int KEY = 1)

       2) 每个case 后面必须接break ,除非集中case的叠加(但case 后面绝对不可以跟continue,continue 用于循环中)

       3) deflaut 后面应用于异常情况的处理,不应将自己的case 最后一种情况介于default 之后,降低程序的容错性

七、const 修饰只读变量

      1.  const 修饰的变量 是只读的,变量的值不可以改变,变量存在于符号表中,没有了存储与读内存的操作;

 #define M 3 //宏常量
const int N=5; //此时并未将N 放入内存中
......
int i=N; //此时为N 分配内存,以后不再分配!
int I=M; //预编译期间进行宏替换,分配内存
int j=N; //没有内存分配
int J=M; //再进行宏替换,又一次分配内存!

      2.  const 修饰的变量定义的时候必须初始化

      3、const 修饰的变量是编译器变量,define 定义的变量是预编译期变量

      4、const 修饰的变量和define修饰的变量的区别

         (1)const 定义的只读变量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数

          (2)const 定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态区),而#define 定义的宏常量在内存中有若干个拷贝。

          (3)#define 宏是在预编译阶段进行替换,而const 修饰的只读变量是在编译的时候确定其值

          (4)#define 宏没有类型,而const 修饰的只读变量具有特定的类型。

      5. const 修饰指针

      const int *p; // p 可变,p 指向的对象不可变
      int const *p; // p 可变,p 指向的对象不可变
      int *const p; // p 不可变,p 指向的对象可变
      const int *const p; //指针p 和p 指向的对象都不可变

八、最异变的关键字volatile

     volatile 修饰的变量表示可以被某些编译器未知的因素更改,比如操作系统、硬件或者其它线程等。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优     化,从而可以提供对特殊地址的稳定访问;

九、struct

      1、空结构体的大小

        struct A

        {

        }aa;

       sizeof(aa)  结果等于 1

     2. 柔性数组

      typedef struct A

      {
            int i;
            int a[];
      }aa;

      sizeof(aa) 等于 4,可见结构的体中的柔性数组的大小是0,不占结构体的空间,仿佛不是结构的体得一部分;

十、union

     存储模式:大端模式和小端模式。
    大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
    小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。

    union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存  取都是从union 的首地址位置开始

    1. 枚举类型所占空间大小

    enum Color
    {
           GREEN = 1,
           RED,
           BLUE,
           GREEN_RED = 10,
           GREEN_BLUE
    }ColorVal;

   sizeof(ColorVal)等于4

   2. 枚举与#define 宏的区别

    1),#define 宏常量是在预编译阶段进行简单替换。枚举常量则是在编译的时候确定其值。
    2),一般在编译器里,可以调试枚举常量,但是不能调试宏常量。
    3),枚举可以一次定义大量相关的常量,而#define 宏一次只能定义一个。

   3. 用函数确定系统的大小端模式

  

[cpp] view plaincopyprint?
 
    1. int checkSystem( )  
    2. {  
    3.    union check  
    4.    {  
    5.      int i;  
    6.      char ch;  
    7.    } c;  
    8.    c.i = 1;  
    9.    return (c.ch ==1);  
    10.  }