C专家编程(3)
段(P117-119)
在一个可执行文件中,主要有三个段:文本段、数据段和bss段。利用size命令,可以查看这三个段的大小。
编程挑战
size
text
data
bss
total
1
16696
1566
600
8
2174
2
16720
1566
600
4032
6198
3
20736
1566
4616
8
6190
4.1
20784
1755
4624
8
6387
4.2
20832
1876
4632
8
6516
5
23440
1876
4632
8
6516
分析结果可知:
数据段保存在目标文件中。(比较2和3的结果可得)
BSS段不保存在目标文件中。(比较1和2的结果可得)
a.out文件的大小受调试状态下编译的影响,但段不受影响。
文本段易受优化措施影响。
段错误(P159-163)
可能导致段错误的常见编程错误是:
坏指针值错误:在指针赋值前就用它来引用内存/向库函数传递一个坏指针/释放指针后再访问它的内容。
改写(overwrite)错误:越过数组边界/在动态分配的内存两端写入数据/改写 ...
C专家编程(2)
理解声明(P64-66)
面对一些复杂的声明形式,可以通过以下两种方法来理解,分别是优先级法和图标法。下面以书上的
char * const *(*next)(); 为例,分别进行分析。
优先级法(P64)
适用规则
解释
A
首先,看变量名next,并注意到它直接被括号所括住
B.1
所以先把括号里的东西作为一个整体,得出“next是一个指向…的指针”
B
然后考虑括号外面的东西,在星号前缀和括号后缀之间作出选择
B.2
规则告诉我们优先级较高的是右边的函数括号,所以得出“next是一个函数指针,指向一个返回…的函数"
B.3
然后,处理前缀*,得出指针所指的内容
C
最后,把char * const解释为指向字符的常量指针
这个声明表示“next是一个指针,它指向一个函数,该函数返回另一个指针,该指针指向一个类型为 char的常量指针”
图表法(P65)
signal函数声明的解析
首先来看一下signal的声明形式:
void (*signal(int sig, void(*func)(int)))(int);
简化后 ...
C专家编程(1)
这一系列主要记录阅读《C专家编程》中,需要注意的一些内容。
寻常算术转换(P22-24)
P23:当执行算数运算时,操作数的类型如果不同,就会发生转换。数据类型一般朝着浮点精度更高、长度更长的方向转换,整型数如果转换为signed不会丢失信息,就转换为signed,否则转换为unsigned。
#define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))int d=-1;if (d < TOTAL_ELEMENTS -2) xxx; // 实际执行不到
sizeof()返回类型为无符号数,比较时d被升级为unsigned int类型。
解决方法是对TOTAL_ELEMENTS强制类型转换为int,即
if (d < (int)TOTAL_ELEMENTS -2)
符号“重载”(P37-38)
许多操作符在不同的场景下会有不同的意义,如static、void、*等。
另外,还有一些符号具有多个容易混淆的意思。
p = N * sizeof * q; // (1)apple = sizeof(int) * ...
使用sparse-checkout命令克隆“部分”代码
在克隆大型项目的时候,可能实际仅需要其中的一部分文件。以micropython为例,我们可能仅需要它的跨平台编译工具mpy-cross,那么只需要用到其中的lib,py及ports中的部分内容即可。
使用git的sparse-checkout命令,可以只拉取指定的目录和文件。
实际上仍然会下载整个仓库,只是显示的时候仅列出指定的内容,所以并不能缩短下载时间。
下面来说明主要的操作流程:
git initgit remote add -f origin https://github.com/micropython/micropython.git # 替换为需要克隆的仓库地址# 1.启用并初始化sparse-checkout功能git sparse-checkout init# 2.添加需要包含的目录或文件git sparse-checkout set lib py mpy-cross ports/unix ports/windows# 3.拉取文件git checkout master # 或者 git pull origin master
后续可以通过 git sparse-ch ...