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

时间:2015-04-27 12:47:27

标签: c++ c typedef c-preprocessor

在浏览一些大量混合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的副本,因为它特别询问了功能签名的含义,而不是更为一般的“有什么区别”。

5 个答案:

答案 0 :(得分:8)

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用作参数类型时,似乎void尝试与$(function($) { $.fn.initPlugin1 = function() { console.log('Initialized Plugin1'); return $(this); }; $.fn.initPlugin1.testFunction = function() { $(this).append('Function 1.'); }; }); 中的不同类型。

答案 1 :(得分:5)

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

typedef void MY_VOID;

如果您尝试使用此代替void来表示函数不带参数:

int f(MY_VOID);

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

所以,如果你真的想通过编写(a)在两种语言中都有效的代码和(b)使用void的这种特殊用法的别名来让自己变得困难,那么别名将不得不是一个宏观。

答案 2 :(得分:3)

评论指的是这样的代码:

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

使用#define是合法的。

答案 3 :(得分:1)

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

C99,6.7.5.3/10:

  

void类型的未命名参数的特殊情况,作为列表中唯一的项目,指定该函数没有参数。

C ++,8.3.5 / 2:

  

如果parameter-declaration-clause为空,则该函数不带参数。参数列表(void)等同于空参数列表。

区别很明显。 C将void作为void类型的未命名参数,并且C ++具有标识符void。前者可以是typedef - ed,后者可以是<。

考虑其原因可能会很有趣。实际上,以下内容在C ++中是合法的,但在C:中是非法的

void fn(int){
}

由于C ++在函数定义中具有未命名(匿名)参数的概念,而C几乎没有......几乎。

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

这绝对没什么意义,因为这种类型的名称参数没有。

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

但我想这不是试图说出像那样疯狂的东西,而是C ++委员会决定放弃&#34; unnamed-void-type-parameter&#34;完全填充并使用&#34;特殊参数列表&#34;。我说好了解。

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

答案 4 :(得分:-1)

你可以同时使用它们,它们正在做同样的事情,所以使用#define的唯一区别就是你将新类型声明为宏。