美文网首页
《C语言深度剖析》读书笔记.md

《C语言深度剖析》读书笔记.md

作者: action爱生活 | 来源:发表于2018-05-09 18:18 被阅读47次

    register

    register 变量必须是一个单个的值,并且其长度应小 于或等于整型的长度。 而且 register 变量可能不存放在内存中,所以不能用取址运算符“&” 来获取 register 变量的地址。

    float 变量与“零值”进行比较

    //EPSINON 为定义好的 精度。
    if((fTestVal >= -EPSINON) && (fTestVal <= EPSINON)); 
    

    volatile

    volatile 关键字告诉编译器 i 是随时可能发生变化的,每次使用它的时候必须从内存中取出 i 的值,因而编译器生成的汇编代码会重新从 i 的地址处读取数据放在 k 中。

    这样看来,如果 i 是一个寄存器变量或者表示一个端口数据或者是多个线程的共享数 据,就容易出错,所以说 volatile 可以保证对特殊地址的稳定访问。

    extern

    extern 可以置于变量或者函数前,以 标示变量或者函数的定义在别的文件中,下面的代码用到的这些变量或函数是外来的,不 是本文件定义的,提示编译器遇到此变量和函数时在其他模块中寻找其定义

    空结构体占用空间大小

    struct student {
    
    }stu;
    

    sizeof(stu)的值是多少呢?

    Visual C++ 6.0上为 1
    编译器认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要 1 个 byte,编译器为每个结构体类型数据至少预留 1 个 byte 的空间。所以,空结构体的大小就定位 1 个 byte。

    struct 与 class 的区别

    struct 的成 员默认情况下属性是 public 的,而 class 成员却是 private 的。

    union 关键字

    union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置 空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所 有的数据成员具有相同的起始地址。

    union StateMachine {
         char character;
         int number;
         char *str;
         double exp;
    };
    

    一个 union 只配置一个足够大的空间以来容纳最大长度的数据成员,以上例而言,最大 长度是 double 型态,所以 StateMachine 的空间大小就是 double 数据类型的大小。
    另外,注意大小端模式对 union 类型数据存储的空间有影响

    typedef 关键字

    typedef struct student {
    
         //code
    }Stu_st,*Stu_pst;
    A),struct student stu1;和 Stu_st stu1;没有区别。
    B),struct student *stu2;和 Stu_pst stu2;和 Stu_st *stu2;没有区别。 这个地方很多初学者迷惑,B)的两个定义为什么相等呢?其实很好
     
    const
    const  int *p;      //p指向的对象不可变(*p不可变)
    int const *p;     //p指向的对象不可变(*p不可变)
    int *const p;     //p不可变,p指向的对象可变
    const int *const p; //前一个 const 修饰*p,后一个 const 修饰 p,指针 p 和 p 指向的对象 都不可变
     
    void Fun(const int i);     //不希望这个参数值被函数体内意外改变。
    const int Fun (void);     //返回值不可被改变。
    

    运算符

    SQR(8)
    

    输出的是:
    The square of 8 is 64.

    预算符

    运算符可以用于宏函数的替换部分。这个运算符把两个语言符号组 合成单个语言符号。

    #define XNAME(n) x ## n
    

    如果这样使用宏:

    XNAME(8)
    

    则会被展开成这样:
    x8

    指针和数组

    A)

    int* p1[10];     // 指针数组,数组的每个值都是指针
    

    “[]”的优先级比“*”要高。p1 先与“[]”结合,构成一个数组的定义,数组名为 p1,int * 修饰的是数组的内容,即数组的每个元素。那现在我们清楚,这是一个数组,其包含 10 个 指向 int 类型数据的指针,即指针数组。
    B)

    int  (*p2)[10];     //数组指针,可以理解为 int (*)[10] p2,实际上就是二维数组p[][10];
    

    “()”的优先级比 “[]”高,“*”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容, 即数组的每个元素。数组在这里并没有名字,是个匿名数组。那现在我们清楚 p2 是一个指 针,它指向一个包含 10 个 int 类型数据的数组,即数组指针。

    函数指针

    A)

    char * fun3(char * p1,char * p2);     //fun3是函数名,p1,p2是参数,其类型为char*型,函数的返回值为char * 类型。
    

    B)

    char * *fun2(char * p1,char * p2);     //与 C)表达式相比,唯一不同的就是函数的返回值类型为 char**
    

    C)

    char * (*fun1)(char * p1,char * p2);     //fun1 不是什么函数名,而是一个 指针变量,它指向一个函数。这个函数有两个指针类型的参数,函数的返回值也是一个指 针。我们把这个表达式改写一下:char * (*)(char * p1,char * p2) fun1; 这样子是不 是好看一些呢?只可惜编译器不这么想。
    

    函数指针数组

    char * (*pf)(char * p)     //函数指针
    char * (*pf[3])(char * p);     //这是定义一个函数指针数组。它是一个数组,数组名为 pf,数组内存储了 3 个指向函数的 指针。pf是数组名
    

    函数指针数组的指针

    char * (*(*pf)[3])(char * p);     //pf是指针,这个指针指向一个包含了 3 个元素的数组;这个数字里 面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个 指向字符的指针的函数。
    

    实战练习

    • 参考答案:
      a) int a;
      b) int a;
      c) int a;
      d) int a[10];
      e) int * a[10];
      f) int (
      a)[10];
      g) int (
      func)(int a);
      h) int (
      func[10])(int a);

    相关文章

      网友评论

          本文标题:《C语言深度剖析》读书笔记.md

          本文链接:https://www.haomeiwen.com/subject/cyeorftx.html