• 《C专家编程》——笔记整理


    第一章:C的时空

    1、可移植的代码——严格遵循标准(ANSI C)的程序
    (1)只使用已确定的特性;
    (2)不突破任何由编译器实现的限制;
    (3)不产生任何依赖编译器定义的或未定义的特性的输出。

    2、无符号类型
    (1)尽量不要在代码中使用无符号类型,以避免增加不必要的复杂性;
    (2)尽量使用有符号类型,在涉及混合类型升级时,不必担心边界情况;
    (3)只有使用位段和二进制掩码是,才可用无符号类型,并使用强制类型转换来确保操作数类型相同;
    (4)有符号类型和无符号类型运算时,会转化成无符号类型,再进行运算;

    第二章:语言特性

    1、差一错误——strlen
    直觉性错误:malloc(strlen(str)) -->> malloc(strlen(str) + 1)

    2、NUL和NULL
    NUL:ASCII码值为0000 0000,常用于结束一个ASCII码字符串,即字符串末尾的'\0',
    NULL:空指针

    3、switch
    (1)fall through:case后面不加break语句时,switch会依次执行下去,除非某些特殊情况,几乎所有的case都需要以break结尾。
    (2)break语句跳出最近的循环语句或者switch语句。

    4、函数的全局可见性
    函数定义时,缺省修饰符的情况下,默认函数作用域为全局可见。指定文件范围时,需要添加static说明。

    5、符号重载
    (1)static:在函数内部,修饰变量时表示变量的值在调用期间保持连续性;在函数这一级,表示函数只对本文件可见;
    (2)extern:用于函数定义,表示全局可见(冗余);用于变量,表示在其他地方定义;
    (3)sizeof:操作符,操作数为类型名时,两边必须加上括号;操作数如果是变量则不必加括号;

    6、运算符的优先级
    (1)运算符*的优先级较低:[]高于*,如int *a[]中a表示的是元素为int指针的数组,即int* (a[]);函数()高于*,如int *fp()中fp表示返回值为int*的函数,即int *(fp());
    (2)算术运算符高于位移运算符,即mas << 4 + lsb表示msb << (4 + lsb);
    (3)建议:牢记乘法和除法优先于加法和减法,在涉及其他的操作符时一律加上括号

    第三章:声明

    1、组合类型

    (1)结构体 struct

    struct 可选的结构标签 {  
    	类型1 标识符1;  
        类型2 标识符2;  
        类型3 标识符3;
    
    	类型N 标识符N;	
    
    } 可选的变量定义;
    

    考虑到可阅读性以及语句功能的单一性,建议变量的声明与类型的声明分开,如:

    // 类型声明  
    struct fruit_tag {
    	int color;
    	int weight;
    	int number;
    };
    
    // 变量定义
    struct s_tag orange;
    
    

    (2)联合体 union
    在联合体中,所有成员都是从便宜地址零开始存储;各个成员的位置存在重叠,某一时刻只有一个成员真正存储在该地址。 常用来节省空间。

    联合体的外部结构基本与结构体相同,仅替换关键字union:

    union 可选的结构标签 {  
    	类型1 标识符1;  
        类型2 标识符2;  
        类型3 标识符3;
    
    	类型N 标识符N;	
    
    } 可选的变量定义;
    

    (3)枚举 enmu
    将一串名字与一串整型值联系在一起,通常也可以使用宏定义实现。一般形式如下:

    enmu 可选的标签 {
    	标识符1;
        标识符2 = 主动赋值;
        标识符3;
    
    	标识符N;
    } 可选的变量定义;
    

    缺省的情况下,标识符的整型值从0开始,下一次标识符的值自动加1,依次下推;如果对某个标识符进行赋值,那么后续的标识符依次加一。

    枚举变量在函数运行时一直存在,而宏定义在预编译时被替换,因此,枚举变量更易于调试代码。

    2、优先级规则

    A 声明从最左边的标识符中读取,然后按照优先级依次读取;  
    B 优先级从高到低依次是:
      B.1 声明中被括号括起来的部分;  
      B.2 后缀操作符:括号()表示函数,方括号[]表示数组;  
      B.3 前缀操作符:星号*表示“指向...的指针”;  
    C 如果const或者volatile关键字后面紧跟类型说明符,则其作用于类型说明符;否则,作用域左边紧邻的指针星号。
    

    示例: char * const *(*next)()
    分析流程:
    A:名称为next;
    B.1:(next),表示next为一个指针;
    B.2: (
    next)(),表示next为一个指向函数的指针;
    B.3: (next)(), 表示next为一个指向函数的指针, 该函数返回的是一个指针;
    C: char * const (next)(), 表示函数返回的指针,指向一个只读的指向char的指针;

    3、typedef与define的区别
    typedef可以看做一种彻底的类型封装,在运行过程中有效;宏定义,仅做替换,在预编译时进行处理。

    尽量避免对结构使用typedef。

    可用作数组、指针和函数的组合类型,以及可移植类型。

    第四章:数组和指针的差异

    待续

  • 相关阅读:
    P1128 [HNOI2001]求正整数
    zabbix-server端监控MySQL服务
    对服务器磁盘、CPU、内存使用状态,设置163邮件告警
    JDK8 的FullGC 之 metaspace
    JDK8-废弃永久代(PermGen)迎来元空间(Metaspace)
    JVM的方法区和永久带是什么关系?
    如何使用start with connect by prior递归用法
    JVM原理讲解和调优
    jvm 性能调优工具之 jstat
    记一次HBase内存泄漏导致RegionServer挂掉问题
  • 原文地址:https://www.cnblogs.com/HZL2017/p/15917086.html
Copyright © 2020-2023  润新知