最近在debug时候遇到一个非常有趣的语法bug。
#define REG_ADDR(x) ((volatile uint32_t *)(uintptr_t)(HU + OFFSET)
i = i =0x4;
READ(REG + i); //我的本意是想在OFFSET的基础再加 i,这样来读取想要的数值。
但实际结果确实:
printf("OFFSET + i =%x\n", READ(REG + i));
10...20...30...
并不是想要的0...4...8
这是因为i被隐式的类型转换了,转换成(volatile uint32_t),而这种类型每加4就等于加了16个字节。
再来看下((volatile uint32_t *)(uintptr_t)(HU + OFFSET)
这个很奇怪吧?之前每见过这种写法,其实它本质上就是类型转换。
C和指针一书中明确说明了:(类型)被称为强制类型转换(cast)
所以((volatile uint32_t *)(uintptr_t)(HU + OFFSET)就是先转化为(uintptr_t)再转换为(volatile uint32_t *)
也就是说最左边的类型转换就是最终的强制类型转换
在实验的时候还遇到另外一个现象,就是sizeof的返回值类型。
printf("%d\n", sizeof(int));
报错:‘%d’ expects argument of type 'int' but ...'long unsigned int'
说明sizeof的返回值在我这台机器的编译器上是long unsigned。sizeof返回值类型本身是size_t 这个在不同编译器可能不一样。