函数签名中 typedef void FOO 与 #define FOO void 的含义

Implications of typedef void FOO vs. #define FOO void in function signatures

在浏览一些大量混合使用 C 和 C++ 的源代码时,我遇到了以下内容(为了保护公司的工作而稍作修改,含义保持不变):

/*
 * Typedefs of void are synonymous with the void keyword in C,
 * but not in C++. In order to support the use of MY_VOID
 * in place of the void keyword to specify that a function takes no
 * arguments, it must be a macro rather than a typedef.
 */
#define MY_VOID void

在此特定上下文中,typedef void MY_VOID#define MY_VOID void 有什么区别?


我认为这不是 this question 的重复,因为它专门询问了关于函数签名的含义,而不是更笼统的 "what's the difference"。

您可以同时使用两者,它们做同样的事情,所以唯一的区别在于使用#define 会将您的新类型声明为宏。

评论引用了这样的代码:

typedef void my_void_t;
my_void_t foo(my_void_t); // Illegal.

使用 #define 是合法的。

一个简单的 C++ 测试程序演示了不同之处:

typedef void VOID;

void f(VOID) {}

int main()
{
    f();
}

编译时(作为 C++),it gives these error:

prog.cpp:5:8: error: '<anonymous>' has incomplete type
 void f(VOID) {}
        ^
prog.cpp:5:12: error: invalid use of 'VOID {aka void}'
 void f(VOID) {}
            ^
prog.cpp: In function 'int main()':
prog.cpp:9:7: error: too few arguments to function 'void f(<type error>)'
     f();
       ^
prog.cpp:5:6: note: declared here
 void f(VOID) {}
      ^

这解释了注释在您的代码中的含义。特别是,当 typedef VOID 用作参数类型 [=23] 时,它似乎试图成为与 void 不同的类型 =].

评论解释了差异。给定 void 的别名:

typedef void MY_VOID;

如果您尝试使用它而不是 void 来指示函数不带参数:

int f(MY_VOID);

C 允许这样做,但 C++ 不允许。

因此,如果您真的想通过编写 (a) 在两种语言中均有效且 (b) 针对 void 的特定用途使用别名的代码来让自己的生活变得困难,那么该别名将必须是宏。

语言标准的摘录可以使一切变得更好!

C99, 6.7.5.3/10:

The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.

C++,8.3.5/2:

If the parameter-declaration-clause is empty, the function takes no arguments. The parameter list (void) is equivalent to the empty parameter list.

区别很明显。 C 将所讨论的 void 作为类型 void 的未命名参数,而 C++ 具有标识符 void。前者可以typedef-ed,后者不能。

仔细想想这其中的原因可能会很有趣。实际上,下面的语句在C++中是合法的,但在C中是非法的:

void fn(int){
}

因为C++在函数定义中有unnamed(匿名)参数的概念,而C没有...差不多。

实际上,一个未命名的参数可以出现在 C 函数定义中:void.

类型之一

这绝对没有意义,因为这种类型没有 named 参数。

除了意义不大之外,参数列表中 void 的这种定义可能会搞砸 C++ 的未命名参数,因为它与它们没有什么不同。该定义本可以修改为 非常非常非常 未命名参数的特例,它没有相应的命名参数,不能与其他命名或未命名参数一起使用,并且不是实际上是一个参数和...

但我猜想 C++ 委员会并没有试图说出如此疯狂的话,而是简单地决定完全放弃 "unnamed-void-type-parameter" 的东西并使用 "special parameter list"。我说好吧。

C 标准呢?出于向后兼容的原因,它可能保留了奇怪的 6.7.5.3/10...