使C源代码中的大常量更具可读性?
我正在研究微处理器的一些代码。
它有一些大的关键常数。
#define F_CPU 16000000UL
在这种情况下,这是CPU频率。 在赫兹。
事实上,如果没有在数字上手动标记光标,则很难判断它是1,600,000,160,000,000还是16,000,000。
如果我将逗号放在#define F_CPU 16,000,000UL
的数字中,它会截断常量。
我使用了一些具有特定数字分隔符的深奥语言,旨在使大数字更具可读性(ex 16_000_000
,主要是用于MCU的语言)。 大型“神奇数字”在嵌入式内容中相当普遍,因为它们需要描述MCU如何与现实世界对话。
在C中有这样的东西吗?
一种可能性就是这样写:
#define F_CPU (16 * 1000 * 1000)
或者
#define MHz (1000*1000) #define F_CPU (16 * MHz)
编辑:其他建议的MHz(x)可能更好
是的,C确实有预处理器分隔符: ##
所以你可以写
#define F_CPU 16##000##000UL
其含义与16000000UL 完全相同 。 (与16 * 1000 * 1000等其他结构不同,您需要注意不要将它们放在乘法可能导致问题的地方。)
也许是这样的?
#define MHz(x) (1000000 * (x)) ... #define F_CPU MHz(16)
另外,我不喜欢#define
s。 通常最好使用enum
或常量:
static const long MHz = 1000*1000; static const long F_CPU = 16 * MHz;
您可以将常量写为计算结果(对于您的示例,为16*1000*1000
)。 更好的是,您可以定义另一个宏MHZ(x)
,并将您的常量定义为MHZ(16)
,这将使代码更加自我记录 – 以牺牲创建名称空间冲突概率为代价。
// constants.h #define Hz 1u // 16 bits #define kHz (1000u * Hz) // 16 bits #define MHz (1000ul * kHz) // 32 bits // somecode.h #define F_CPU (16ul * MHz) // 32 bits
笔记:
-
int
是8位MCU上的16位。 - 只要有可能,16位字面值将被优化到8位字节(具有8位指令)。
- 有符号整数文字是危险的,特别是如果与按位运算符混合使用,这在嵌入式系统中很常见。 默认情况下使所有内容都无符号
- 考虑使用变量表示法或注释表明常量是32位,因为大多数8位的32位变量非常慢。
您可以使用科学记数法:
#define F_CPU 1.6e+007
要么:
#define K 1000 #define F_CPU (1.6*K*K)
它可能有助于将常量定义为:
#define F_CPU_HZ 16000000UL
这样你就知道它里面有什么类型的数据。 在我们的SW中,我们有一些外设需要设置各种预分频器,所以我们有一个像这样的#defines
:
#define SYS_CLK_MHZ (48) #define SYS_CLK_KHZ (SYS_CLK_MHZ * 1000) #define SYS_CLK_HZ (SYS_CLK_KHZ * 1000)
另一种方法是在更通用的宏中使用##预处理器运算符
#define NUM_GROUPED_4ARGS(a,b,c,d) (##a##b##c##d) #define NUM_GROUPED_3ARGS(a,b,c) (##a##b##c) #define F_CPU NUM_GROUPED_3ARGS(16,000,000UL) int num = NUM_GROUPED_4ARGS(-2,123,456,789); //int num = (-2123456789); int fcpu = F_CPU; //int fcpu = (16000000UL);
这是某种所谓的WYSIWYG但不能免于滥用。 E. g。 你可能会让编译器抱怨
int num = NUM_GROUPED_4ARGS(-2,/123,456,789); //int num = (-2/123456789);
但它不会。