【问题标题】:Doubts about Macros in C对 C 中的宏的怀疑
【发布时间】:2015-05-25 07:06:02
【问题描述】:
#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 MSEC /1000l 中的 /1000l 是什么意思?为什么使用 /。

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

【问题讨论】:

  • 编辑您的问题以包含C 标签;你能告诉我们你是如何编译你的代码的吗?你正在使用什么编译器?对于gcc,我有error: invalid suffix "MHZ" on integer constant。但如果我将其修改为 SysTick_Config(96 MHZ * 2.5 MSEC);
  • 可能结尾不是'1',而是字母'l',整数常量的长后缀。
  • 谢谢你..它的'l'而不是1..我的编译器显示l和1是一样的......所以,可能我很困惑
  • @tapanchawda 你为什么不编译它看看会发生什么?
  • 我已经编译好了..没有错误

标签: c macros


【解决方案1】:

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

/1000l 只是除以 1000。

【讨论】:

  • 听起来更像是评论而不是答案
  • 嗯,我在回答以前在 OP 中的问题,但 OP 已经改变了。 耸耸肩
  • 我知道这种感觉,移动目标
  • 我已取消注释,除非 OP 再次更改。 :)
  • 从我们目前看到的情况来看,这似乎很有可能:)
【解决方案2】:

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

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

这样就不会产生混淆,并且可以避免任何优先级问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多