点点废话
最近没有再将rax的源码往下看,rax对于一个新手来说还是体量过大,在尝试自己写写,在写的时候遇到了一些坑,也体会到了rax的一些写法的精妙之处,记录一下。
宏定义函数的注意点:
我定义了这样一个宏定义函数:
1 | #define radixNthChild(h, n) \ |
我这样调用这个函数:
1 | radixNthChild(new_cur, new_cur->size - 1) |
这样一个调用大家觉得有问题吗?嗯,肯定是有问题的,不然我说啥?。
这里,按照我们一般的调用函数的思路,这样一个调用的运行过程是这样的:
- 计算出new_cur->size - 1
- 带入radixNthChild函数
实际上恰恰相反,宏定义的处理在预编译时(g++ -E),宏定义是将对于的定义替换掉,所以在
预编译后的结果如下:
1 | # 363 "radix_tree.c" |
可以看到是 : + new_cur->size - 1 * sizeof(void)
而不是我所想的: + (new_cur->size - 1) * sizeof(void)
可以得出其过程其实是:
- 函数宏定义替换
- 运行时计算
结论: 在宏定义函数调用时注意括号的问题,不加括号可能会由于运算符优先级而 导致表达式意义与我们想的有出入?
地址运算注意点
先给出这样一个结构体:
1 | struct test { |
int main(void) {
cout << sizeof(test) << endl;
test* p = new test;
fprintf(stdout, "%p:%p:%p:%p\n", p, p + 1, (char*)p + 1, (int*)p+1);
return 0;
}
在这样一个测试代码中,大家觉得p + 1, (char)p + 1, (int)p+1这三个结果,相对于p的数值相差多少呢?
运行结果是这样的。类型与地址的运算是有着密切关系的。
- p + 1是一个默认情况, 这时1的意义是一个p的地址宽度
- (char*)p + 1,p被解释为char类型指针,指向的地址被解释为char,于是1就是一个char的地址宽度。
总结: 在计算地址时,要注意运算符左边值的类型。你加上的1可能并不是一个字节的大小。
这是我边看rax边实现的一个小练习,欢迎大家指教:https://github.com/LurenAA/radix_tree ,好想要个star,求求了,兄弟萌:kissing_heart: