使用g ++进行奇怪的零初始化

时间:2011-04-28 07:33:57

标签: c++ gcc g++

我遇到了以下代码的奇怪行为,同时使用g ++ 4.4.3进行了初始化。

  int main()

    {

        int x(int());

        int y = int();

        cout << x << "  " << y <<  endl;
    }

结果是:

1 0

“y”的值如预期的那样为0,但x的值奇怪地为“1”!

在VS2008上产生以下链接错误(函数声明,但没有定义):

unresolved external symbol "int __cdecl x(int (__cdecl*)(void))"

任何人都可以解释这个奇怪的g ++行为吗?

6 个答案:

答案 0 :(得分:24)

int x(int());被解析为函数声明。

它声明了一个名为x的函数,返回一个int并接受一个参数,该函数的函数类型返回int并且不接受任何参数。

这被称为最令人烦恼的解析。

答案 1 :(得分:13)

为了补充GMan的回答herex是一个函数定义),为什么1

输出为1的原因是在调用地std::cout << x处,函数衰减为指向函数的指针(该语言不允许您将函数作为参数传递给其他函数,与数组一样,执行指向的隐式转换。现在,ostream没有带有函数指针的重载,编译器尝试选择转换为任何可用的重载。此时它发现最佳转换序列是bool并且它打印1(指针不是0)。

您可以通过更改行为来检查此问题,您可以使用std::cout << std::boolalpha << x,这将打印true而不是1。另外,值得注意的是VS是正确的,因为表达式std::cout << x需要取x的地址,然后函数使用并且程序是如果没有该功能的定义,则形成不良。您可以通过提供定义再次检查:

int f() {}
int main() {
   int x(int());      // 1
   x( &f );           // 2
}
int x( int(*)() ) {   // 3
   std::cout << "In x" << std::endl;
}

我已在function(1)的定义中手动执行从pointer-to-functionx的转换以及使用参数f(2)的调用 - 请注意,1中的声明和3 中的定义是相同的签名,如果不这样做,编译器将执行&中的x( &f )

答案 2 :(得分:4)

添加更多parens:

int main()

    {

        int x((int()));

        int y = int();

        cout << x << "  " << y <<  endl;
    }

现在x是一个int,而不是一个函数。

答案 3 :(得分:3)

正如其他人所说,x是一个功能声明。由于没有为函数指针类型定义预定义的ostream插入器,因此g ++似乎使用隐式bool转换(用于检查函数指针是否为NULL)来找到输出它的方法。

另一方面,Visual C ++抱怨声明的函数x从未被定义,因此它无法完成链接。我怀疑在这种情况下g ++足够聪明,可以看到函数永远不会被调用,因此不用担心链接。

您可以尝试在代码中添加函数int x(int(*)()) { return 0xdeadbeef; }的虚拟定义,然后查看MSVC对其执行的操作。

答案 4 :(得分:2)

C ++将第一个解释为函数的声明。

答案 5 :(得分:1)

这个

int x(int());

实际上是一个函数声明,输入是以下签名的函数

int fn(void)

传递给std::cout <<的函数指针转换为bool(1),因为它是非NULL指针。