使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); 

但它不会。