《深入C语言和程序运行原理》阅读笔记

入口函数

所有C语言程序都会使用main函数作为入口函数。入口函数,就是指程序开始运行时,代码中会被首先调用的那个函数。在main函数中,我们可以通过它接收到的实际参数,来选择性地访问程序在开始运行时,由用户传递给程序的外部参数。
main函数在执行结束时会返回一个整数,用于表示程序执行完毕的状态,通常返回数字0表示程序正常退出,返回其他数字则代表异常退出。

int main(int argc, char* argv[]) {
	xxx;
	return EXIT_SUCCESS;
}

EXIT_SUCCESS是标准库中定义的宏常量,作为程序退出的返回值。这个宏常量的实际值为0.

数组

数组初始化

用大括号初始化可以用指派初始化的方式,明确这些项在数组中的具体位置。

// 其中CONN是定义的结构体
const CONN conns[] = {// 构造一个数组,包含三个 CONN 对象:
	// 指派初始化,设置第三个元素
	[2] = {1, 80, BOOL_TRUE, IP, {.ip = "127.0.0.1"}},
	[0] = {2, 8080, BOOL_FALSE, IP, {.ip = "192.168.1.1"}},
	{3, 8088, BOOL_FALSE, Host, {.host_name = "http://localhost/"}}
};

结构体与联合体

数组conns内部,存放有若干个类型为CONN的结构对象。
在C语言中,结构体和联合体通常用来组织复杂类型的自定义数据。在结构体中,所有定义字段的对应数据按照内存连续的方向排列。而在联合体中,定义的字段同一时间只会有一个生效。

typedef struct { // 定义结构体
	size_t id;
	unit16_t port;
	// C99的标准_Bool类型
	bool closed;
	IP_ADDR_TYPE addr_type;
	// C11标准的匿名联合体
	union {
		char host_name[256];
		char ip[24];
	};
} CONN;

前面数组初始化中也有联合体初始化,需要用.引用某个具体成员。

控制结构

// 循环遍历数组conns中的内容
for (size_t i = 0; i < (sizeof(conns) / sizeof(CONN)); ++i) { // 遍历上述CONN数组,并打印其中给的内容
	printf(
		"Port: %d\n"
	);
}
  • swiitch语句:选择
  • while语句: 迭代
  • goto语句:跳转

指针

借助指针,我们能够灵活地操控程序享有的内存资源。

inline static const char* findAddr(const CONN* pip) { // 定义函数findAddr,用于打印CONN对象信息
	assert(pip != NULL); // 运行时断言,判断传入的CONN指针是否有效;
	return pip->addr_type == Host ? pip->host_name : pip->ip;
}

将数组conns中各个元素的地址传递给了函数findAddr,而该函数则接受一个指向CONN类型对象的常量指针。
通过该const指针,我们无法在函数内部修改指针所指向对象的值,这在一定程度上保证了函数仅能够拥有足够完成其任务的最小权限。

编译器对C源代码的处理过程分为几个阶段,其中,宏是最先被处理的一个部分。
在代码的开头处,我们通过宏指令"#include"引入了程序正常运行需要的一些外部依赖项,这些引入的内容会在程序编译时得到替换。
“#define”指令定义了相应的宏常量与宏函数,而其中的宏函数typename则使用到了C11标准新引入的_Generic关键字,以用来实现基于宏的泛型。

断言

静态断言

// 保证结构类型 CONN 的大小不会超过一定的阈值
static_assert(sizeof(CONN) <= 0x400, "the size of CONN object exceeds limit.");  // 静态断言,判断 CONN 对象的大小是否符合要求;

动态断言

// 保证传递给函数 findAddr 的 CONN 对象指针不为空
assert(pip != NULL); // 运行时断言,判断传入的CONN指针是否有效;

在 C 代码中,我们通常会使用断言,来对某种需要支持程序正常运行的假设性条件进行检查。而当条件不满足时,则在程序编译或运行时终止,并向用户抛出相应的错误信息。C 语言提供静态与动态两种类型的断言,其中静态断言会在代码编译时进行检查;而动态断言则会在程序运行过程中,执行到该断言语句时再进行检查。

内联函数

在函数 findAddr 的定义代码中,我们为其添加了名为 inline 的关键字。通过使用该关键字,我们可以“建议”编译器将该函数的内部逻辑直接替换到函数的调用位置处,以减少函数调用时产生的开销。这种方式通常使用在那些函数体较小,且会被多次调用的函数上,以产生较为显著的性能提升。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值