怀疑C中的宏

时间:2015-05-25 07:06:03

标签: c macros

#define MHZ *1000000l
#define MSEC /1000l

这是函数定义

unsigned int SysTick_Config(unsigned int ticks)
{
  if (ticks > SysTick_LOAD_RELOAD_Msk) 
  return (1);   // Reload value impossible 

  STRELOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; // set reload register 

  return (0);  // Function successful 
}

如下所述调用函数

 SysTick_Config(96MHZ * 2.5MSEC);

我的疑问是关于使用的宏。写96MHZ意味着它被(96 * 1000000l)取代? 96乘以1000000?  另外,#define FiEC / 1000l中的/ 1000l是什么意思?为什么是/ used。

我正在使用IAR嵌入式工作台

2 个答案:

答案 0 :(得分:0)

在像这样的数字旁边使用宏时,数字和宏之间需要有空格。在这种情况下,您应该看到编译器错误。

/1000l只是除以1000。

答案 1 :(得分:0)

您需要在文字和宏之间添加空格,否则编译器会将它们视为无效的整数和浮点常量:

SysTick_Config(96 MHZ * 2.5 MSEC);

预处理后,该行将扩展为

SysTick_Config(96 *1000000l * 2.5 /1000l); // trailing l makes the type
                                           // of the constant a long
                                           // int instead of a regular int

请注意,如果您编写类似

的内容,这种编程风格会导致问题
SysTick_Config(a + b MHZ * c - d MSEC); 

您需要确保明确地将事物分组,例如

SysTick_Config((a+b) MHZ * (c-d) MSEC);

我知道有些人喜欢用这种方式编写代码,认为它是自我记录的。我认为这是一个错误,不仅因为它可能导致优先问题。

更安全的方法是使用带有参数的类似函数的宏:

/**
 * When creating macros for arithmetic expressions, it's a good
 * idea to use parentheses around each macro argument and the
 * entire macro expansion itself; this way you can avoid
 * precedence issues if you pass an expression like a+b to
 * the macro.   
 */
#define TO_MHZ(x)  ((x) * 1000000L) // use uppercase L to avoid confusion
#define TO_MSEC(x) ((x) / 1000L )   // with the digit 1

并将其用作

SysTick_Config( TO_MHZ(96) * TO_MSEC(2.5) );

扩展为

SysTick_Config( ((96) * 1000000L) * ((2.5) / 1000L) )

SysTick_Config( TO_MHZ(a+b) * TO_MSEC(c-d) );

扩展为

SysTick_Config( ((a+b) * 1000000L) * ((c-d) / 1000L) );

这种方式没有混淆,您可以避免任何优先级问题。