• 编程珠玑之关键字(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. 用函数确定系统的大小端模式

      

      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.  }  
  • 相关阅读:
    kvm介绍
    正式班D24
    正式班D23
    正式班D21
    正式班D20
    正式班D19
    正式班D18
    正式班D17
    正式班D16
    正式班D15
  • 原文地址:https://www.cnblogs.com/heyp/p/3798781.html
Copyright © 2020-2023  润新知