【问题标题】:Macro without definition in CC中没有定义的宏
【发布时间】:2013-03-06 19:19:19
【问题描述】:

没有定义的宏函数有什么用途/适用性:

#ifndef __SYSCALL
#define __SYSCALL(a, b)
#endif

可以在Linux系统的头文件/usr/include/asm/msr.h中找到这个宏

我还注意到以下类型的宏。

#define _M(x) x

并且唯一的理由是定义这种我认为可以使代码统一的宏。比如#define SOMETHING (1 << 0)。这种宏还有其他隐藏(更好)的用途吗?

示例的答案将非常有帮助。还 有人可以给我一个文本/链接来阅读这个。

【问题讨论】:

  • __SYSCALL 宏仅在某些架构上定义。
  • 让代码更统一是什么意思?
  • @Hogan 对不起,我无法用 Uniform 清楚地表达我的意思是这样的#define something 1&lt;&lt;0

标签: macros c-preprocessor


【解决方案1】:

这种形式的宏最常见的情况之一:

#define _M(x) x

旨在为仅支持 C 的原始 K&R 方言的编译器提供向后兼容性,该方言早于现在普遍存在的 ANSI C 方言。在该语言的原始 K&R 方言中,声明函数时未指定函数参数。 1989 年,ANSI 对该语言进行了标准化并进行了多项改进,包括声明参数类型数量的函数原型。

int f(int x, double y); /* ANSI C. K&R compilers would not accept this */

int f(); /* Function declared in the original K&R dialect */

虽然现在支持 C 的原始 K&R 方言的编译器很少(或已绝迹),但在需要同时支持这两种编译器的情况下编写了很多软件,而宏提供了一种支持这两种编译器的简单方法。仍然有很多提供这种向后兼容性的标头。

为了向 K&R 编译器提供向后兼容性,许多头文件具有以下内容:

#if ANSI_PROTOTYPES
#  define _P(x) x
#else
#  define _P(x) ()
#endif

...

int f _P((int x, double y));

如果ANSI_PROTOTYPES 定义已正确设置(由用户或某些先前的#ifdef 逻辑设置),那么您将获得所需的行为:

  • 如果定义了 ANSI_PROTOTYPES,则定义扩展为 int f(int x, double y)
  • 如果未定义 ANSI_PROTOTYPES,则定义扩展为 int f()

【讨论】:

  • 感谢 sfstewman!你的回答真的很好。我添加了更多用途。
  • "这种形式的宏最常见的情况之一......" - 这个论点现在仍然有效吗?
  • @icepack 用这种方式编写的新标头并不多,但这是您看到的那种形式的宏的更常见用途之一。我想不出我见过的很多其他用途。
【解决方案2】:

这通常与条件表达式一起使用,通过将宏预处理为空来禁用宏。例如(简体):

#ifdef DEBUG
#define ASSERT(x) if(!(x)) { abort(); }
#else
#define ASSERT(x) /* nothing */
#endif

【讨论】:

【解决方案3】:

只是对我的问题的跟进。

我得到了很好的答案。但我还添加了一些更有用的示例,其中没有定义的宏很有用,将来会发现它很有用:

(1)Why do I see THROW in a C library?
用于在 C 和 C++ 之间共享头文件。宏名称为_THROW(x)

#ifdef __cplusplus
    #define __THROW(x) throw(x)
#else
    #define __THROW(x)
#endif  

(2) to eliminate warnings when a function parameter isn't used:
此用途适用于 c++。在 C 中它会导致 an error too few arguments 但在 C++ it works with no error: (codepad linked)

#define UNUSED(x)
int value = 0;
int foo(int UNUSED(value))
{
    return 42;
}
int main(){
   foo(value);
}

(为此我在我的问题中添加了 c++ 标签)

另外,
(3):#define _M(x) x的使用如下,只是为了让代码统一排列:

/* Signed.  */
 # define INT8_C(c)      c
 # define INT16_C(c)     c
 # define INT32_C(c)     c
 # if __WORDSIZE == 64
 #  define INT64_C(c)    c ## L
 # else
 #  define INT64_C(c)    c ## LL
 # endif

文件是:/usr/include/stdint.h

【讨论】:

    【解决方案4】:

    这意味着使用该宏的代码将有条件地预处理为空。

    作为简单示例,请考虑调试代码、日志记录或断言。

    【讨论】:

      【解决方案5】:

      这可能是一个调试宏或平台宏。例如,假设我有一个附加到 INT3 的调试器。我调试的时候可能有这个

       #define debug() INT3()
      

      然后为了安全起见,我会将其添加到生产代码中(以确保我将它们全部取出)

       #define debug()
      

      这看起来有点相似

      在某些情况下,在某些系统上,此代码可能需要进行调用,例如在某个 CPU 架构或操作系统上。但在您的系统上,它只是没有操作。

      【讨论】:

        猜你喜欢
        • 2018-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多