1. 三字母词

三字母词即用三个字符合起来表示另一个字符,它可以使C环境在某些缺少一些必需字符的字符集上实现。

??( [    ??< {    ??= #
??) ] ??> } ??/ \
??! | ??' ^ ??- ~

2. 转义字符

\ddd  表示由八进制数ddd的数值所代表的字符
\xddd 表示由十六进制数ddd的数值所代表的字符

3. 字面值前/后缀

(1) 在多字节字符常量前面添加L,则它是宽字符常量。如:L'X', L'e^'等。

(2) 在整数字面值后面添加L或l,可以使这个整数被解释为long型;添加U或u则用于把数值指定为unsigned型;两者均添加则被解释为unsigned long型。

4. 当for/while循环体无事可做时,单独用一行来表示一条空语句是个比较好的做法,这样清晰地表明循环体是空的,不至于使人误会接下来的一条语句才是循环体。

while ((ch = getchar()) != EOF && ch != '\n')
; // 单独用一行来表示空语句是种好做法。

5. 如果你可以互换地使用指针表达式和下标表达式时,应该使用哪一个?从可读性上看,下标显然更好;从效率上看,下标绝不会比指针更有效率,但指针有时会比下标更有效率。

// use array's index
int arr[], i;
for (i = ; i < ; ++i)
arr[i] = ; // 每次循环时都要计算i * 4 // use pointer
int arr[], *ptr;
for (ptr = arr; ptr < arr + ; ++ptr) // 只需在编译时计算一次1*4,运行时不执行乘法
*ptr = ;

6. 字符串查找

char *strchr(char const *str, int ch);  // 寻找字符ch第一次出现的位置
char *strrchr(char const *str, int ch); // 寻找字符ch最后一次出现的位置
char *strpbrk(char const *str, char const *group); // 寻找一组字符中的任意一个第一次出现的位置
char *strstr(char const *s1, char const *s2); // 寻找子字符串s2第一次出现的位置
size_t strspn(char const *str, char const *group); // 寻找字符串前缀
size_t strcspn(char const *str, char const *group ); // 寻找非字符串前缀
char *strtok(char *str, char const *sep); // 分隔并提取字符串

7. 字符分类

isspace(char ch); // 空白字符:' ', '\f', '\n','\r', '\t', '\v'
isxdigit(ch); // 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
isalpha(ch); // 字母
isalnum(ch); // 字母或数字
ispunct(ch); // 标点符号,任何不属于数字或字母的可打印符号

8. 内存操作

void *memcpy(void *dst, void const *src, size_t len);
void *memmove(void *dst, void const *src, size_t len);
void *memcmp(void const *a, void const *b, size_t len);
void *memchr(void const *a, int ch, size_t len);
void *memset(void *a, int ch, size_t len);

9. 位域(bit field)

(1) 优点:节省存储空间;可以很方便地访问一个整型值的部分内容。

(2) 缺点:可移植性较弱:(a) int位域被当作有符号数还是无符号数,不能确定;(b) 位域中位的最大数目不确定。许多编译器把位域成员的长度限制在MAX_INT内,但32位的机器和16位的机器的MAX_INT值不同。(c) 当一个声明指定了两个位域,且第2个位域比较大以致无法容纳于第1个位域剩余的位时,编译器有可能把第2个位域放在内存的下1个字,也可能直接放在第1个位域后面,从而在两个内存位置的边界上形成重叠。

10. 动态分配内存

只释放一块动态分配的内存的一部分是不允许的,动态分配的内存必须整块一起释放。如果要缩小一块动态分配的内存,应该使用realloc。

pi = (int *)malloc( * sizeof(int));
...
free(pi + ); // error! you can't free only part of the memory.

11. 函数指针的应用

(1) 回调函数。用户把一个函数指针作为参数传递给其他函数,后者将“回调”用户的函数。当你编写的函数必须能够在不同的时刻执行不同类型的工作或执行职能由函数调用者定义的工作时,你都可以使用这个技巧(此时往往需要把参数类型声明为void *)。许多窗口系统使用回调函数连接多个动作,如拖拽鼠标和点击按钮来指定用户程序中的某个特定函数。

(2) 转移表。适用于对不同的输入调用不同的函数的场合。

// 袖珍式计算器
double add(double, double);
double sub(double, double);
double mul(double, double);
double div(double, double);
...
double (*oper_func[])(double, double) = {add, sub, mul, div, ...};
result = oper_func[oper](op1, op2);

12. 字符串常量

当一个字符串常量出现在表达式中,它的值是个指针常量。编译器把这些指定字符的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针。因此,类似数组名,我们可以对字符串常量进行下标引用、间接访问以及指针运算。

"xyz" + ; // 结果为一个指针,指向字符'y'
*"xyz"; // 结果为字符'x'
"xyz"[]; // 结果为字符'z'
printf("%s\n", "**********" + - n); // 打印n个星号*,注意0 <= n <= 10

13. 预定义符号

14. 宏和函数的区别

15. 输入/输出函数

(1) 错误报告

void perrno(char const *message);  // <stdio.h>

(2) 终止执行

注意exit与return不同,return是退出当前函数,exit是退出整个程序。

void exit(int status);  // <stdlib.h>

(3) I/O总览

(4) 文件流

FILE *fopen(char const *name, char const *mode);  // 打开文件,失败时返回NULL
int fclose(FILE *f); // 关闭文件,成功时返回0,失败时返回非零值

(5) 字符I/O

// 读入字符
int fgetc(FILE *stream); // 函数
int getc(FILE *stream); // 函数或宏
int getchar(); // 从标准流stdin中读入字符 // 输出字符
int fputc(int c, FILE *stream); // 函数
int putc(int c, FILE *stream); // 函数或宏
int putchar(int c); // 向标准流stdout输出字符 // 撤销字符
int ungetc(int c, FILE *stream); // 把一个先前读入的字符返回到流中

(6) 行I/O

// 输入字符串
char *fgets(char *buf, int buf_size, FILE *stream);
char *gets(char *buf); // 从标准输入流stdio中读入字符串 // 输出字符串
int fputs(char const *buf, FILE *stream);
int puts(char const *buf); // 向标准输出流stdout输出字符串

(7) 格式化的行I/O

// 格式化输入
int scanf(char const *format, ...); // 从标准输入流stdio中读入
int sscanf(char const *str, char const *format, ...); // 从字符串str中读入
int fscanf(FILE *stream, char const *format, ...); // 从文件流stream中读入 // 格式化输出
int printf(FILE *stream, char const *format, ...); // 输出到标准输出流stdout
int sprintf(char *buf, char const *format, ...); // 输出到字符串buf
int fprintf(FILE *stream, char const *format, ...); // 输出到输出流stream

(8) 刷新和定位函数

int fflush(FILE *stream); //刷新文件流,清空缓冲区。
long ftell(FILE *stream); // 返回流的当前位置
int fseek(FILE *stream, long offset, int from); // 定位流的位置

(9) 改变缓冲方式

void setbuf(FILE *stream, char *buf); //设置数组buf,用来对流进行缓存
int setvbuf(FILE *stream, char *buf, int mode, size_t size); // mode用来指定缓冲的类型(完全缓冲、行缓冲、不缓冲)

(10) 流错误函数

int feof(FILE *stream); // 流处于文件尾时返回真
int ferror(FILE *stream); // 出现读写错误时返回真
void clearerr(FILE *stream); // 重置流的错误标志

(11) 文件操纵函数

int remove(char const *filename); // 删除文件
int rename(char const *oldname, char const *newname); // 重命名文件

16. 运行时环境

(1) 堆栈帧。函数存储变量和其他值的地方。

(2) 一个函数分成三个部分:函数序(prologue),函数体(body),函数跋(epilogue)三部分。函数序用于执行函数启动需要的一些工作,例如为局部变量保留堆栈中的内存。函数跋用于在函数即将返回之前清理堆栈。

《C和指针》读书笔记的更多相关文章

  1. csapp读书笔记-并发编程

    这是基础,理解不能有偏差 如果线程/进程的逻辑控制流在时间上重叠,那么就是并发的.我们可以将并发看成是一种os内核用来运行多个应用程序的实例,但是并发不仅在内核,在应用程序中的角色也很重要. 在应用级 ...

  2. CSAPP 读书笔记 - 2.31练习题

    根据等式(2-14) 假如w = 4 数值范围在-8 ~ 7之间 2^w = 16 x = 5, y = 4的情况下面 x + y = 9 >=2 ^(w-1)  属于第一种情况 sum = x ...

  3. CSAPP读书笔记--第八章 异常控制流

    第八章 异常控制流 2017-11-14 概述 控制转移序列叫做控制流.目前为止,我们学过两种改变控制流的方式: 1)跳转和分支: 2)调用和返回. 但是上面的方法只能控制程序本身,发生以下系统状态的 ...

  4. CSAPP 并发编程读书笔记

    CSAPP 并发编程笔记 并发和并行 并发:Concurrency,只要时间上重叠就算并发,可以是单处理器交替处理 并行:Parallel,属于并发的一种特殊情况(真子集),多核/多 CPU 同时处理 ...

  5. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  6. 读书笔记--SQL必知必会18--视图

    读书笔记--SQL必知必会18--视图 18.1 视图 视图是虚拟的表,只包含使用时动态检索数据的查询. 也就是说作为视图,它不包含任何列和数据,包含的是一个查询. 18.1.1 为什么使用视图 重用 ...

  7. 《C#本质论》读书笔记(18)多线程处理

    .NET Framework 4.0 看(本质论第3版) .NET Framework 4.5 看(本质论第4版) .NET 4.0为多线程引入了两组新API:TPL(Task Parallel Li ...

  8. C#温故知新:《C#图解教程》读书笔记系列

    一.此书到底何方神圣? 本书是广受赞誉C#图解教程的最新版本.作者在本书中创造了一种全新的可视化叙述方式,以图文并茂的形式.朴实简洁的文字,并辅之以大量表格和代码示例,全面.直观地阐述了C#语言的各种 ...

  9. C#刨根究底:《你必须知道的.NET》读书笔记系列

    一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...

  10. Web高级征程:《大型网站技术架构》读书笔记系列

    一.此书到底何方神圣? <大型网站技术架构:核心原理与案例分析>通过梳理大型网站技术发展历程,剖析大型网站技术架构模式,深入讲述大型互联网架构设计的核心原理,并通过一组典型网站技术架构设计 ...

随机推荐

  1. MVC、MVP、MVVM概念解析

    详细请看阮一峰网站 1.MVC Model(数据) - View(视图) - Controller(业务逻辑) 通信方式:单向 交互方式两种,如下 应用:(BackBone)不完全和设计模式一致 2. ...

  2. Vue项目开发最新、最全代码规范文档

    Vue项目开发最新.最全代码规范文档 2019年02月21日 10:43:49 yw00yw 阅读数 337   一. 目录结构 |— build 构建脚本目录 |— build.js 生产环境构建( ...

  3. hive的两种使用方式

    hive的两种使用方式 1,hive shell的方式 启动命令: bin/hive 2.beeline客户端方式 首先在一个机器上启动hive thrift服务 bin/hiveserver2 在其 ...

  4. 动态规划——区间DP,计数类DP,数位统计DP

    本博客部分内容参考:<算法竞赛进阶指南> 一.区间DP 划重点: 以前所学过的线性DP一般从初始状态开始,沿着阶段的扩张向某个方向递推,直至计算出目标状态. 区间DP也属于线性DP的一种, ...

  5. fatal: unable to access 'https://github.com/Homebrew/homebrew-core/'

    LibreSSL SSL_read: SSL_ERROR_SYSCALL, errno 54 安装curl "https://nodejs.org/dist/latest/node-${VE ...

  6. PyTricks-使用namedtuple以及dataclass的方式定义类

    from collections import namedtuple from dataclasses import dataclass # 以前简单的类可以使用namedtuple实现. Car = ...

  7. Linux设备驱动 之 中断处理程序

    注册中断处理程序 中断处理程序是管理硬件驱动程序的组成部分:如果设备使用中断,那么相应的驱动程序就注册一个中断处理程序: 驱动程序通过request_irq()函数注册,并且激活给定的中断线,以处理中 ...

  8. [.NET] ConfuserEx脱壳工具打包

    [.NET] ConfuserEx脱壳工具打包 ConfuserEx 1.0.0脱壳步骤        Written by 今夕何夕[W.B.L.E. TeAm] 1.先用UnconfuserEx把 ...

  9. 交叉编译多平台 FFmpeg 库并提取视频帧(转)

    交叉编译多平台 FFmpeg 库并提取视频帧 转  https://www.cnblogs.com/leviatan/p/11142579.html 本文档适用于 x86 平台编译 armeabi.a ...

  10. centos7 搭建FTP

    通过yum安装vsftpd yum install -y vsftpd 修改vsftpd的配置文件 vim /etc/vsftpd/vsftpd.conf 修改配置文件如下: 1.不允许匿名访问 an ...