C++中的一些反直觉逻辑记录
条件判断
函数往往对唯一情况的处理是return 0
例如strncmp函数,如果字符串str1与str2相同,那么return 0。但是0代表的是假,那么配合 if 语句的编程手法是将判断语句写成
!strncmp(buf,"quit",4) 【!0】为真,从而通过 if 可以去处理这个唯一情况。
指针中的*
C语言的命名从后往前读: 遇到*解释为:point to ,对于指针的定义和使用也是如此!
结构体
在C语言中,结构体(struct)的内存布局遵循内存对齐规则。这种对齐机制是为了提高CPU访问内存的效率,但会导致结构体的实际大小可能大于各成员变量大小的简单相加。
每个数据类型都有自己的对齐要求(alignment),通常等于其自身大小。例如:
char:1字节对齐
int:4字节对齐(32位系统)
double:8字节对齐
指针:4字节(32位系统)或8字节(64位系统)
计算方式为:成员字节数 + 成员间填充字节数 + 结构体末尾填充字节数。其中:填充字节数由成员之间的对齐要求决定。最终大小需满足结构体整体对齐要求。,在成员相互之间或结构体末尾,可插入**填充字节(padding)**以满足对齐要求
示例:
struct ListNode {
int val;
char s[12];
struct ListNode *next;
};分析:
现在,我们一步步计算:
- int val;
从偏移量 0 开始。
val 占用 4 字节。其对齐要求为 4 字节。
偏移量 0 是 4 的倍数,所以不需要填充。
val 占据内存范围:[0, 3]。
当前偏移量:4。
- char s[12];
当前偏移量为 4。
s 数组占用 12 字节。char 的对齐要求是 1 字节。
偏移量 4 是 1 的倍数,无需填充。
s 占据内存范围:[4, 15]。
当前偏移量:16。
- struct ListNode *next;
当前偏移量为 16。
next 是一个指针,在64位系统上占用 8 字节。其对齐要求为 8 字节。
偏移量 16 是 8 的倍数,无需填充。
next 占据内存范围:[16, 23]。
当前偏移量:24。
至此,所有成员都已放置完毕,结构体的“原始”总大小为 24 字节。
内存布局:
[val(4)][s(12)][next(8)]
val 和 s 之间无需填充(4 + 12 = 16,已对齐到4字节)。
next 需从8字节边界开始,当前地址为16(4 + 12),无需填充。
总大小:4 + 12 + 8 = 24字节。
最大成员对齐为8字节(next),因此结构体总大小需是8的倍数。24本身是8的倍数,无需额外填充。