C Primr Plus 笔记整理

Chapter 1 初识C语言

  • 标准: C89(ANSI C)/C90、 C99、C11
  • 目标代码文件 + 启动代码 + 库函数 -> 可执行文件

Chapter 2 C 语言概述

Chapter 3 数据和C

  1. 整数: int, 变式: short, long, long long, unsigned, signed.
    • 后缀: l/L, ll/LL, ull/ULL.
    • 打印: %d, %ld, %hd (short)
    • 溢出: 当达到能表达的最大值时,重新从起点开始。unsigned 从0开始,signed 从 -xxxx开始。
  2. 浮点数:float, double, long double.
    • 存储方式:符号位、指数部分、尾数部分。C 标准规定,float至少精确标示小数点后6位有效数字。
    • 小数的二进制表示: 乘以2,整数部分作为小数点后的第一位,再将小数部分乘以2,得到的整数部分作为作为小数点后的第二位,以此类推,直到小数部分为0
    • 小数点形式,指数形式 2.0e10 2.0E10。c99/c11提供了通过十六进制和2的幂来表示的指数形式: 2^5-> 0x1p+5
    • 后缀: f/F, l/L(long double).
    • 打印: %f,%lf; %e,%le; %a,%la(十六进制);
    • 上溢(inf)、下溢(0)、NaN(not a number)、舍入错误:一个较大大浮点数,加1再减去原值,结果不等于1。缺少足够的位来保证正确的运算。2.0e20 + 1 - 2.0e20 = ?
  3. 字符: char, 也可表示较小的整数。
    • C语言中,多个连续的字符串等价于一个组合的字符串
  4. 布尔: _Bool, C99提供 stdbool.h 头文件,让 bool 成为 _Bool 的别名。
  5. 复数、虚数 C99
    • float _Complex, double _Complex, long double _Complex
    • float _Imaginary, double _Imaginary, long double _Imaginary
    • 包含头文件complex.h,便可用complex替代_Complex,用imaginary替代_Imaginary.用I代替-1的平方根。
  6. 衍生类型: 数组、指针、结构、联合
    • sizeof() C 语言内置运算符,以字节为单位给出指定类型的大小。C99提供%zd用于打印sizeof()的返回值。
  7. 进制
    • 八进制 前缀:0 printf()打印:%#o
    • 十六进制 前缀:0x 0X printf()打印:%#x %#X p计数法
  8. 可移植类型
    • 相关头文件: stdint.h, inttypes.h
    • (精确宽度整数类型) int32_t: 32位有符号整数类型。在int为16位,long为32位的系统中,将int32_t作为了long的别名
    • 最小宽度类型 int_least8_t: 可容纳8位有符号整数值的类型中宽度最小的类型的别名 C99 C11
    • 最快最小宽度类型 int_fast8_t: 对8位有符号值而言运算最快的整数的别名 C99 C11

使用printf()参数的数量、类型一定要匹配
刷新缓冲区——从缓冲区把数据发送到屏幕或文件。刷新输出:缓冲区满、遇到换行符、需要输入、fflush()函数

Chapter 4 字符串和格式化输入输出

  1. C语言中,字符串被存储在char类型的数组中。空字符’\0’标志字符串的结束。
  2. scanf()遇到空白(空格、制表符、换行符)停止读取输入。%s
  3. sizeof()以字节为单位给出对象大小。strlen()给出字符串的长度。–%zd
  4. 定义常量
    • 预处理器定义 #define 编译时替换 没有分号,通常全大写。(建议)
    • const C90 限定一个变量为只读。
      相关头文件:limits.h float.h
  5. printf()转换说明, 一定要匹配!!!
    把以二进制格式存储在计算机中的值转换成一系列字符(字符串)以便于显示。并不替换原始值,只是翻译
    • char: %c
    • 字符串: %s
    • 指针: %p
    • sizeof(): %zd
    • int: %d, %i
    • unsigned int: 八进制-%o, 十进制-%u, 十六进制-%x, %X
    • double: %e, %E, %f, %F, %g %G:(根据值得不同,自动选择%f或%e/%E)
    • %a %A: 浮点数、十六进制数和p计数法
    • 打印%: %%
  6. printf()转换说明修饰符
    • 标记
      • -: 左对齐
      • +: 显示正负号
      • 空格: 空格覆盖+标记的正号
      • #:将结果转换为另一种形式。%#o: 以0开始,%#x: ox %#X: 0X
      • 0: 前导0填充字段宽度。
    • 数字 最小字段宽度,若不够容纳,系统会使用更宽的字段
    • .数字 精度
      • %e、%E、%f: 表示小数点右边数字位数
      • %g、%G: 表示有效数字最大位数
      • %s: 表示待打印字符的最大数量
      • 整型转换: 表示待打印数字的最小位数,如有必要,使用前导0
      • 只使用. 表示其后跟随一个0, %.f 同 %.0f, 即舍去小数部分
    • h: 与整型转换说明一起使用。表示 (unsigned) short int. eg: %hu, %hx, %hd
    • hh: 与整型转换说明一起使用。表示 (unsigned) short char. eg: %hhu, %hhx, %hhd
    • j: 与整型转换说明一起使用。表示 intmax_t 或 uintmax_t 类型的值。定义在stdint.h中。
    • l: 与整型转换说明一起使用。表示 (unsigned) long int
    • ll: 与整型转换说明一起使用。表示 (unsigned) long long int
    • L: 与浮点转换说明一起使用。表示 long double
    • t与整型转换说明一起使用。表示 ptrdiff_t 类型的值,两个指针差值的类型。
    • z与整型转换说明一起使用。表示 size_t 类型的值 (sizeof返回的类型),可移植性考虑
  7. printf()返回值:打印字符的个数,错误返回-1.
  8. 代码中给长字符串断行的三种方式:
    • 多个printf();
    • 使用’\’和 Enter 键组合。作用:光标移至下一行,且不含换行符。
    • ANSI C 中引入的字符串连接。 两个双引号括起来的字符串以空白隔开,C 编译器看作是1个字符串。
  9. scanf() 将输入的字符(串)转换为整数、浮点数、字符或字符串。参数列表中使用的是指针。
  10. 修饰符
    • printf()中: *代替字符段宽度, 程序中通过其他参数传递
    • scanf()中: *跳过相应的输入项 抑制赋值

Chapter 5 运算符、表达式和语句

  1. 基本运算符: ‘=’ ‘+’ ‘-’ ‘*’ ‘/’ (没有指数运算符,标准数学库提供了pow())
    • 概念
      • 数据对象:用于储存值得数据存储区域
      • 左值: 用于标识特定数据对象的名称或表达式。新标准术语:对象定位值
      • 右值:能赋给可修改左值得量,且本身不是左值。
    • 除法,整数除法结果为整数,发生截断,丢弃整个小数部分,而不是四舍五入。趋零截断
  2. 其他运算符
    • sizeof以及size_t类型。size_t: 无符号整数类型,(标准类型)。 %zd转换说明
      • typedef: 为现有类型创建别名。
    • 求模运算符:% 只能用于整数运算。负数求模,结果的符号与第一个运算符的符号相同。
    • 递增递减运算符: ++ – 生成的机器语言效率更高
      • 前缀模式
      • 后缀模式
      • 优先级高,只有圆括号的优先级高于递增运算符。
      • 只能作用于可修改的左值。
  3. 术语:副作用、序列点
  4. 类型转换
    • 需要转换时, unsigned 及 signed 的 char 和 short 都会被转换为int, 有必要时转换为unsigned int.
    • 涉及两种类型的运算,两个值会被转换成比两种类型更高的级别
    • 类型级别: long double > double > float > unsigned long long > long long > unsigned long > long > unsigned int > int
    • 运算时,根据两个运算对象升级;赋值时,根据变量类型,会导致升级或降级。降级会截断,类型降级危险
    • 函数参数传递, char和short被转换为int,float转换为double. 函数原型会覆盖自动升级
    • 强制类型转换: (type)

Chapter 6 控制语句:循环

  1. 3种循环
    • for 入口条件循环
    • while 入口条件循环
    • do while 出口条件循环,循环体至少循环一次
  2. 关系运算符 ‘>’ ‘>=’ ‘==’ ‘<=’ ‘<’ ‘!=’
    • 优先级: 低于算术运算符,高于赋值运算符
  3. 真值
    • 数值方面:非0为真,0为假
    • 关系表达式为真,求值为1;关系表达式为假,求值为0
    • _Bool C99 包含头文件stdbool.h, 让bool成为_Bool的别名,true和false分别定义为1和0的符号常量,可与C++兼容。C++将bool、true、false定义为关键字。
      *尽量使用while(goats)而不是while(goats != 0)
      如果待比较的值是常量,放在 ‘==’ 左边有助于编译器捕捉错误*
  4. 其他赋值运算符
    • += -= *= /= %=
    • 逗号运算符 ,:
      char ch, date; 此处为分隔符,不是运算符
      • 被分隔的表达式从左往右求值。逗号是一个序列点,左侧项的副作用在程序执行右侧项之前发生
        a++, b = 5 * a; 不常用
        y = 249,500; 不是语法错误,相当于y = 249;500;
      • 整个逗号表达式的值是右侧项的值
        x = (y = 3, (z = ++y + 2) + 5); 糟糕
        y = (249,500); 不是语法错误,y = 500;

Chapter 7 控制语句:分支和跳转

  1. if语句
    • if
    • if… else…
    • if… else if… else…
    • else与if配对问题:与最近的没有被花括号括起来的if配对
  2. 字符输入输出函数: getchar(); putchar();字符处理函数头文件ctype.h
    • 字符测试函数
      • isalnum() 字母或数字
      • isalpha() 字母
      • isblank() 标准的空白字符(空格、水平制表符、换行符)
      • iscntrl() 控制字符 eg: Ctrl+B
      • isdigit() 数字
      • isgraph() 除空格之外任意可打印字符
      • islower() 小写
      • isprint() 可打印字符
      • ispunct() 标点符号
      • isspace() 空白字符(空格、换行符、换页符、回车符、垂直制表符、水平制表符)
      • isupper() 大写字母
      • isxdigit() 十六进制数字符
    • 字符映射函数 不修改原始参数,只返回已修改的值
      • tolower()
      • toupper()
  3. 逻辑运算符: &&、||、!
    • 备选拼写:iso646.h头文件 and、or、not
  4. 条件运算符: ?:
  5. 循环辅助
    • continue
    • break
  6. 多重选择: switch和break
    • ”default: ” 可以写在任何一个case标签可以出现的位置。当switch表达式的值与所有case标签都不匹配时,default子句后面的语句会被执行。每个switch语句只能有一条default子句,但可以出现在语句列表的任何位置。
  7. goto语句 谨慎使用,或者根本不用
    • 标签

Chapter 8 字符输入/输出和输入验证

  1. 输入
    • 缓冲输入
      • 完全缓冲I/O:缓冲区被填满才刷新缓冲区(内容被发送到目的地)
      • 行缓冲I/O:出现换行符时刷新
    • 无缓冲输入,立刻回显
  2. 单字符I/O: getchar(), putchar()

    • stdin: 键盘输入
    • stdout: 屏幕输出
  3. 文件结尾 EOF 定义在stdio.h中
  4. 重定向

Chapter 9 函数

  1. 递归
    • 尾递归:递归调用置于函数的末尾,return语句之前。
  2. 头文件, 存放函数原型、已定义的符号常量
  3. &运算符 获取变量地址。 %p
  4. 指针, 间接运算符 *

Chapter 10 数组和指针

  1. 数组初始化
    • C99新增:指定初始化器 eg: int a[10] = { [5] = 6 };
  2. 数组、指针、函数
    • ”int a[]” 只能用于函数原型和函数定义中
  3. 指针操作:
    • 赋值
    • 解引用 *
    • 取址:指针自身的地址
    • 指针与整数相加: 与指针指向类型的大小相乘,然后把结果与初始地址相加
    • 递增指针
    • 指针减去一个整数
    • 递减指针
    • 指针求差: 指向的两个元素的距离
    • 比较,必须指向相同的类型。
      注意事项:不能解引用未初始化的指针。未初始化的指针,其值是一个随机值。创建指针时,系统只分配了储存指针本身的内存,并未分配储存数据的内存。
  4. 通过数组名或指针传递参数,使用const保护原始数据。
  5. 指针和多维数组 eg: a[4][2] a = &a[0] = a[0] = &a[0][0]
    • 声明一个指向多维数组的指针: int (*p)[2];
      必须使用圆括号,[]的优先级高于解引用符。指向一个数组,该数组内含2个int类型值。
      如何理解? 以a[4][2]为例,将指针声明为int,仅与a[0]的类型匹配,说明指向一个int类型的值,数组名a是首元素的地址,首元素是一个内含两个int类型值的一维数组。
      int *p[2]; 声明了一个指针数组,含两个元素,指向int类型
  6. C与C++中const的区别
    • C中不允许通过const变量设置数组长度。
      const int size = 10;
      int a[size] = {0}; /* C中错误,C++中可以 */
    • C++中指针赋值检查更严格。
      const int a;
      const int *p1 = &a;
      int *p2;
      p2 = p1; /C++不允许,C只给出警告 /
  7. 变长数组(VLA) C99
  8. 常量

    • 符号常量
    • 字面量
      • 复合字面量:(int [2]) {1,2} 或(int []){1,2} 必须在创建的同时使用,可以通过指针记录地址来用,可以传递给匹配的形参  
  9. 创建数组的三种方法

    • 声明数组时,用常量表达式表示数组维度。可用静态内存或自动内存创建。
    • 声明变长数组(C99),用变量表达式表示数组维度。只能在自动内存中创建。
    • 声明一个指针,调用malloc(),将返回值赋给指针。该指针可以是静态的或自动的

Chapter11 字符串和字符串函数

  1. 定义字符串
    • 字符串常量, 静态存储类别,只会被存储一次,整个程序的生命周期内存在。用双引号括起来的内容被视为指向该字符串储存位置的指针,类似于将数组名作为指向该数组位置的指针
    • char类型数组
    • 指向char类型指针
  2. 输入/输出相关函数
    • 显示字符串函数
      • puts: 显示字符串,自动添加换行符
      • fputs() 与fgets()配合,不自动添加换行符;若要显示在屏幕上,以标准输出stdout为参数
      • printf()
    • 读取字符串函数
      • gets() 读取整行,直到换行符停止,丢弃换行符。unsafe,C11已废除
      • fgets() 遇到换行符储存; 读入从键盘输入的数据,以标准输入stdin为参数,定义在stdio.h中
      • gets_s(),C11新增,可选扩展,编译器不一定支持
      • scanf() %s只能读取1个单词
    • 自定义输入/输出函数: 利用getchar()和putchar()
  3. 数组和指针的区别
    • 数组名是常量,指针通常为变量。
      • 两者都可以使用数组表示法 []
      • 两者都可以进行指针加法操作 *(数组名/指针 + 整数), 但只有指针能进行递增操作
      • 不能通过指向字符串字面量的指针来修改字符串字面量
        建议: const char *p = “string”;
  4. 字符串数组
    • 指向字符串的指针数组 const char * str[2] = {“Hello”, “World”}; //占用字节少 但不可修改
    • char类型数组的数组(二维数组) char str[2][6] = {“Hello”, “World”};
  5. 处理字符串函数 头文件string.h
    • strlen()
    • strcat() strncat() 拼接字符串
    • strcmp() strncmp() 比较字符串
    • strcpy() strncpy() 拷贝字符串, 第一个不必指向数组的开始,可以拷贝数组的一部分
    • sprintf() 头文件stdio.h 把数据写入字符串,而不是打印在显示器上。
    • 其他函数: strchr(), strpbrk(), strrchr(), strstr()
  6. 命令行参数, main()参数
    • 没有参数 void
    • 2个参数
      • argc: argument count
      • argv: argument value
  7. 字符串转数字
    头文件stdlib.h
    • atoi(), atol(), atoll(), atof() 字符串转int, long, long long, double.
    • strtol(), strtoul(), strtod()…更智能, 检查首字符是否为数字,甚至指定进制

Chapter 12 存储类别、链接和内存管理

  1. 作用域,可访问标识符的区域
    • 块作用域
    • 函数作用域: 仅用于goto语句标签, 即使一个标签首次出现在函数的内存块中,它的作用域也延伸到整个函数。
    • 函数原型作用域: 用于函数原型中的形参名,范围从形参定义处到原型声明结束。编译器只关心形参类别,形参名(如果有)无关紧要。只有在变长数组中,原型中的形参名才有用。另外,函数定义中的形参具有块作用域
    • 文件作用域
  2. 翻译单元: 源代码文件和包含的所有头文件被看作是一个翻译单元。C预处理用头文件的内容替换#include指令。
  3. 链接。C变量有三种链接属性。
    • 外部链接: 变量具有文件作用域,可延伸至其他翻译单元。 简称全局作用域或程序作用域
    • 内部链接: 变量具有文件作用域,只能在一个翻译单元中使用。简称文件作用域。 存储类别说明符:static
    • 无链接:具有块作用域、函数作用域、函数原型作用域的变量。
  4. 存储期
    • 静态存储期: 程序执行期间一直存在。文件作用域变量(无论内部链接还是外部链接)和加关键字static的块作用域变量。对文件作用域变量,关键字static表明的是链接属性而非存储期
    • 线程存储期:用于并发程序设计。从被声明到线程结束一直存在。关键字: _Thread_local, 每个线程都会获得该变量的私有备份
    • 自动存储期: 块作用域的变量
    • 动态分配存储期
  5. 存储类别

    存储类别生命周期作用域链接声明方式
    自动自动块内
    寄存器自动块内,使用关键字:register
    静态外部链接静态文件外部所有函数外
    静态内部链接静态文件内部所有函数外,使用关键字:static
    静态无链接静态块内,使用关键字static
    • 自动变量:
      • 存储类别说明符auto auto变量在C++中用法完全不同,编写C/C++兼容程序,最好不要使用auto关键字
      • 自动变量不会默认初始化!,其值是随机值。
    • 寄存器变量
      • 访问和处理速度快
      • 无法获得寄存器变量的地址
      • 使用register只是发出请求,编译器可能会忽略
    • 外部链接的静态变量
      • 使用定义在另一个文件中的外部变量,须加关键字:extern。也可使用extern来说明使用本文件中定义的外部变量。
      • 只能使用常量表达式初始化,不能通过变量初始化。如未初始化,会自动初始化为0
  6. C99和C11标准要求编译器识别局部标识符的前63个字符和外部标识符的前31个字符
  7. 声明
    • 定义式声明: 定义 只能有一个
    • 引用式声明
  8. 存储类别和函数
    • 外部函数(默认)
    • 静态函数 使用关键字:static
    • 内联函数(C99新增)
      除非使用关键字static,否则一般函数声明都默认为extern
  9. 相关函数
    头文件stdlib.h
    • 随机函数和静态变量
      • rand(): 伪随机数生成器 均匀分布
      • srand()
    • 分配、释放内存
      • malloc() 返回void*,通用指针。
      • calloc()
      • free()
    • exit() “EXIT_FAILUE, EXIT_FAILURE”两个返回值在所有系统中都能正常工作
  10. 类型限定符
    • const
      • 在C++中,默认状态下,const对象仅在本文件内有效,若要在其他文件中使用,无论定义和声明都加extern关键字
      • 若将const变量放在头文件中,必须加static声明。否则所有包含该头文件的源文件中都有一份定义式声明。优点:方便。缺点:数据重复。
    • volatility
      • 代理(而不是变量所在的程序)可以改变该变量的值。
      • 用于硬件地址和线程中共享数据。
      • 涉及编译器优化
    • restrict: C99新增。
      • 允许编译器优化某部分代码以更好地支持计算。
      • 只能用于指针,表明该指针是访问数据对象的唯一且初始的方式。
      • 可用于函数形参中的指针。编译器假定在函数体内其他标识符不会修改该指针指向的数据,编译器尝试对其优化。
    • _Atomic C11 原子类型, 用于并发程序设计。
  11. 旧关键字的新位置 C99

Chapter 13 文件输入/输出

  1. 文件模式
    • 文本模式
    • 二进制模式
  2. 标准文件, C程序会自动打开3个文件。
    • stdin: 标准输入
    • stdout: 标准输出
    • stderr: 标准错误输出
  3. 相关函数

    • exit()与return()区别
      • 在main()中,最初的调用,两者作用相同。如果在递归中,exit()退出程序,而return()将控制权交给上一级。
      • 初main()以外的其他函数中,调用exit()也能结束整个程序。
    • fopen() fclose()
      • 打开文件的模式: “r”, “w”, “a”, “r+’, “w+”, “a+”, “rb”, “wb”, “ab”… unix/linux只有一种文件类型,带b字母的模式与不带b字母的模式相同。 C11提供带x字母的模式。
      • 成功返回指向FILE类型的指针。并不指向实际的文件,而是指向一个包含文件信息的数据对象。
    • getc() putc()
    • fprintf() fscanf()
    • rewind() 回到文件开始处。
    • fgets() fputs()
    • fseek() ftell() 随机访问

      • 文件起始点
      模式偏移量起始点
      SEEK_SET文件开始处
      SEEK_CUR当前位置
      SEEK_END文件末尾
      • ftell()返回当前位置
    • fgetpos() fsetpos()
    • ungetc() 把指定的字符放回输入流中。
    • fflush() 刷新缓冲区
    • setvbuf() 创建供标准I/O函数替换使用的缓冲区
      int setvbuf(FILE *fp, char *buf, int mode, size_t size);
      mode取值
      • _IOFBF: 完全缓冲,在缓冲区满时刷新
      • _IOLBF: 行缓冲,缓冲区满或写入一个换行符时
      • _IONBF: 无缓冲
    • 二进制I/O fread() fwrite()
    • feof() ferror() 收到EOF时,区分是否真正到达文件尾而不是发生错误。

Chapter 14 结构和其他数据形式

  1. 结构 struct
    • 结构的标记名可选。
    • 初始化
      • 按顺序用逗号分隔成员的初始化项(声明时用分号分隔各项)。
      • 初始化器 C99/C11 点运算符,顺序任意
    • 结构数组
    • 嵌套结构
    • 指向结构的指针
      • 与数组不同,结构名并不是结构的地址,初始化结构指针时要用&
      • 访问时用 -> 或 (*指针名).成员名
    • 允许把一个结构赋值给另一个结构,即使成员是数组,也可以
    • 结构中的字符数组,指向char的指针(谨慎使用,初始化指针,利用malloc()申请合适的存储空间,利用free()释放)
    • 复合字面量和结构
      • (struct 结构名){ 初始化列表 }
    • 伸缩型数组成员 C99
    • 匿名结构C11
    • 链式结构
  2. 联合 union
    同一个存储空间中存放不同的数据类型(不是同时存储)。
    • 编译器分配足够的空间以便存储联合声明中占用最大字节的类型。
    • 初始化联合
      • 用同类型的联合初始化
      • 初始化联合的第一个元素
      • C99 使用指定初始化器
    • C11 匿名联合
  3. 枚举类型 enum 声明符号名称来表示整型常量
    • C允许枚举变量使用++运算符,C++不允许
    • 默认情况下,枚举列表中的值为 0, 1, 2…
    • 声明时,可以为枚举常量指定整数值
  4. typedef 为某一类型自定义名称
    可看作定义变量时,在前加typedef关键字,变量名成为新类型名。
    • 与#define的区别
      • typedef创建的符号名仅限于类型,不能用于值。
      • typedef由编译器解释而不是预处理器。
      • 在受限范围内,typedef比#define更灵活
  5. 其它复杂声明
    • ’*’ ‘()’ ‘[]’ 的优先级
      • 数组名后的[]和函数名后的()优先级相同,二者比 ‘*(解引用运算符)’的优先级高。
      • ()和[]从左往右结合
  6. 函数和指针
    • 函数的类型: 返回值、形参
    • 声明一个指向函数的指针, 可将函数声明中的函数名替换为(*指针名)
      另:函数名是指针,可以互换使用。
    • 函数名的几种用法
      • 函数原型
      • 函数定义
      • 函数调用
      • 用作指针
      • 用作指针参数

Chapter 15 位操作

  1. 有符号整数的表示
    • 用1位存储符号 缺点:有两个0: +0 -0 8位可表示 -127~127
    • 二进制反码: 反转每一位形成负数 。
    • 二进制补码:
      1位表示符号,确定负值时,用9位100000000减去负数的位组合,结果为该负值的量。
      • 二进制补码表示,获得相反数:反转每一位,再加1.
  2. 二进制浮点数
    分两部分存储:二进制小数和二进制指数。
    • 二进制小数: 以2的幂作分母
  3. 按位运算符:
    • 按位取反: ~
    • 按位与: &, &=
    • 按位或: |, |=
    • 按位异或: ^, ^=
    • 用法:掩码、打开位(设置位)、关闭位(清空位)、切换位、检查位
  4. 移位运算符
    产生一个新的位值,但不改变其运算对象。
    • 左移 <<
    • 右移 >>
    • 用法:针对2的幂进行快速乘法和除法; 提取某些位
  5. 位字段
    • singed int 或 unsigned int 类型变量中的一组相邻的位。
    • 通过结构声明来建立,为每个字段提供标签,并确定该字段的宽度。
    • C以unsigned int作为位字段结构的基本布局单元。即便结构中唯一的成员是1位字段,该结构的大小(所占位数)也是unsigned int类型的大小。
  6. 对齐特性
    • _Alignof: 给出一个类型的对齐要求。
    • _Alignas: 指定一个变量或类型的对齐值。不应该要求小于该类型的基本对齐值。
    • aligned_alloc() 内存分配,动态对齐 C11
      添加stdalign.h头文件,可将alignas和alignof分别作为别名使用。

Chapter 16 C预处理器和C库

  1. 预处理指令
    • #define 宏 替换体
      • 类函数宏 区别于函数调用
      • 替换体,记号型字符串而非字符型字符串。字符型字符串,把空格视为替换体的一部分;记号型字符串,把空格视为替换体中各记号的分隔符。
      • 双引号字符串中的字符被视为普通文本,不是一个可被替换的记号。若要在字符串中包含宏参数,使用#号。
      • ##: 预处理器粘合剂。把两个记号组合成一个记号。
      • 变参宏: 宏参数列表中最后的参数写成省略号 … _ VA_ARGS _ 用在替换部分
    • #include 文件包含
    • #undef: 取消已定义的#define指令
    • 条件编译
      • #ifdef或#ifndef, #else, #endif;
        • #ifndef 还可用于防止多次包含一个文件。
      • #if, #elif
        • #if defined VAX 可替代 #ifdef VAX
    • #line : 重置 _ _ LINE _ _ 和 _ _ FILE _ _ 宏报告的行号和文件名。
    • #error: 让预处理器发出一条错误信息。
    • #pragma _Pragma
    • _Generic: C11关键字。泛型表达式不是预处理指令, 但常用作#define宏定义的一部分。
  2. 预定义宏
    • _ _ DATE _ _
    • _ _ FILE _ _
    • _ _ LINE _ _
    • _ _ STDC _ _
    • _ _ STDC _ _ HOSTED _ _
    • _ _ STDC _ _ VERSION _ _
    • _ _ TIME _ _
    • _ _ func _ _ :函数名
  3. 函数说明符
    • inline: 内联函数
    • _Noreturn: 调用完成后函数不返回主调函数。 exit()是一个示例。
  4. C库
    • 数学库 头文件math.h
    • 通用工具库
      • 随机数生成器
      • 查找和排序函数
      • 转换函数
      • 内存管理函数
        几个函数:
        exit()和atexit()
        qsort()
        memcpy()和memmove()
    • 断言库 头文件 assert.h
      • assert() 运行时检查,若为假,向标准错误写信息并调用abort()终止程序。
      • _Static_assert() 编译时检查。
      • 关闭assert(): #define NDEBUG
    • 可变参数 stdarg.h
      用法较为复杂。

Chapter 17 高级数据表示

  1. 链表
    • 结构不能含有与本身类型相同的结构,但是可以含有指向同类型结构的指针。–>定义链表的基础
    • 头指针 head: 指向链表的第一项
    • next 指针: 指向下一下。最后一项的next为NULL.
  2. 队列 FIFO
    使用链表实现时
    • 新项只能添加到链表的末尾。
    • 只能从链表的开头移除项。
  3. 二叉查找树
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值