这个C宏是什么意思?
What does this C macro mean?
查看fm_transmitter源代码,我偶然发现了这个经常使用的宏。
#define ACCESS(base, offset) *(volatile unsigned*)((int)base + offset)
我猜它是一个基数和偏移量的总和,转换为 int,然后重新转换为无符号指针,然后再次转换为指针?
此宏提供对以字节为单位测量的偏移量的访问。您可以将其重写为
#define ACCESS(base, offset) *(volatile unsigned*)&((char*)base)[offset]
只是原始版本通过 int
类型而不是 char*
类型进行运算。
请注意,使用此宏可能会调用未定义的行为:不能保证生成的指针正确对齐,并且如果数据以 int
变体以外的其他类型写入,则违反了也有严格的别名规则。
还有,选择int
来做指针运算是一个很糟糕的选择,至少应该通过size_t
或uintptr_t
来计算,以保证指针在转换为整数类型期间不会被截断。我重写的版本没有这个具体问题,但是,两个版本都存在未定义行为的危险。
最后,正如 Olaf 在评论中正确指出的那样,转换为 volatile unsigned*
也是一个坏主意,因为这种类型的宽度是实现定义的。转换为 volatile uint32_t*
可能更适合与硬件通信。
查看fm_transmitter源代码,我偶然发现了这个经常使用的宏。
#define ACCESS(base, offset) *(volatile unsigned*)((int)base + offset)
我猜它是一个基数和偏移量的总和,转换为 int,然后重新转换为无符号指针,然后再次转换为指针?
此宏提供对以字节为单位测量的偏移量的访问。您可以将其重写为
#define ACCESS(base, offset) *(volatile unsigned*)&((char*)base)[offset]
只是原始版本通过 int
类型而不是 char*
类型进行运算。
请注意,使用此宏可能会调用未定义的行为:不能保证生成的指针正确对齐,并且如果数据以 int
变体以外的其他类型写入,则违反了也有严格的别名规则。
还有,选择int
来做指针运算是一个很糟糕的选择,至少应该通过size_t
或uintptr_t
来计算,以保证指针在转换为整数类型期间不会被截断。我重写的版本没有这个具体问题,但是,两个版本都存在未定义行为的危险。
最后,正如 Olaf 在评论中正确指出的那样,转换为 volatile unsigned*
也是一个坏主意,因为这种类型的宽度是实现定义的。转换为 volatile uint32_t*
可能更适合与硬件通信。