我有一个裸机软件环境,可以在多个架构上运行,例如ARM 32-bit v7
/ARM 64-bit v8
和自定义的内部架构:我们称之为ARCHX
:
首先如何在ARM32
、ARM64
和ARCHX
上定义不同的数据类型:
(注意:ARM64
在此示例中使用LP64
编程模型)。
- ARM32/ARM64/ARCHX 国际: 32/
- 32/16 长: 32/
- 64/32
- 指针: 32/64/16
我已经实现了一个位宏:
#define BIT(n) (0x1U << (n))
现在ARCHX
如果在 int 上使用BIT
(ARCHX
中的 16 位),这会给出一个错误:
警告:班次计数太大,结果未定义
现在,向此宏添加UL
可以解决此问题,但通常可能会导致其他体系结构出现问题。
所以我的问题是:
BIT
宏的这个定义是否不能在架构和编译器之间移植,因为我需要在某些架构上使用UL
,在某些架构上使用U
,甚至在某些组合上使用ULL
(ARM64
和LLP
编程模型?
也许BIT
宏应该重命名并分为BIT16
、BIT32
和BIT64
,并按体系结构实现,而不是所有体系结构的通用BIT
宏?
首先,绝对没有理由使用这样的宏来隐藏非常基本的功能。x |= 1U << n;
比晦涩的x |= BIT(n);
清晰得多.始终假设阅读您的代码的人知道 C 语言,但不了解您的秘密宏语言。
因此,您应该做的第一件事是摆脱宏。
话虽如此,可移植性是通过使用stdint.h
的类型来实现的。
uint32_t x = (uint32_t)1U << n;
完全可移植到任何已知的计算机。
同样,您也可以使用标准UINTn_C
文字格式和类型
uint32_t x = UINT32_C(1) << n;
UINT32_C
宏可用于使可移植的无符号 32 位常量。
#include <stdint.h>
#define BIT(n) (UINT32_C(1) << (n))
int main(void)
{
return BIT(10);
}
您可以通过针对不同平台的配置定义来解决此问题。 比方说
#ifdef SYSTEM_A
#define BIT_BASE_VALUE 0x1U
#else
#ifdef SYSTEM_B
#define BIT_BASE_VALUE 0x1UL
#endif
#endif
#define BIT(n) (BIT_BASE_VALUE << (n))