在C中,将函数指针赋值给适当类型的变量会给出“无法转换...在赋值时”

时间:2011-01-10 10:04:53

标签: c++ c function-pointers

采用以下C / C ++代码:

#include <stdlib.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*foo(bool))(int);  // foo is &(bool→(int→int))
  foo = baz;
}

尝试编译它(gcc或g ++)给出:

$ g++ test.cc
test.cc: In function ‘int main()’:
test.cc:9: error: assignment of function ‘int (* foo(bool))(int)’
test.cc:9: error: cannot convert ‘int (*(bool))(int)’ to ‘int (*(bool))(int)’ in assignment

自己检查:它声称无法转换的两种类型完全相同。为什么它声称它们不相容?

编辑1 :使用typedef时(建议使用)问题就会消失,如下所示:

int main() {
  typedef int (*int2int)(int);
  typedef int2int (*bool2_int2int)(bool);
  bool2_int2int foo;
  foo = baz;
}

编辑2 :编译器当然是对的。正如许多人所指出的,我的原始代码的问题是foo中的main()是函数的声明,而不是函数指针。因此,赋值中的错误不是冲突类型,而是分配给函数,这是不可能的。正确的代码是:

#include <stdlib.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*(*foo)(bool))(int);  // foo is &(bool→(int→int))
  foo = &baz;
}

5 个答案:

答案 0 :(得分:7)

代码实际上是错误的。问题是这一行:

int (*foo(bool))(int);  // foo is &(bool→(int→int))

......并不代表你认为的意思。它被解释为名为“foo”的函数的声明。这很有道理。想一想 - 如果你想转发声明“baz”,你会放int (*baz(bool))(int);,对吧?另外,由于baz是一个返回函数指针的函数,而foo是一个返回函数指针的函数的指针,你不期望语法更复杂吗?

您将foo声明为与baz相同类型的函数,而不是指向与baz相同类型的函数的指针。

从编译器中,第一个错误消息是有用的 - 它告诉你assignment of function,即你试图分配给一个函数,这是一个错误。

我甚至没有尝试在没有typedef的情况下编写正确的解决方案:-)这里有一些编译代码,我认为是正确的,使用typedef:

#include <stdlib.h>
#include <stdbool.h>

typedef int(*IntReturnsInt)(int);

int inc(int i) { return i+1; } 
IntReturnsInt baz(bool b) { return b ? &abs : &inc; }

int main() {
  IntReturnsInt (*foo)(bool b);
  foo = baz;
}

在这个例子中,双功能指针概念更清晰 - IntReturnsInt是函数指针类型,foo是指向返回IntReturnsInt的函数的指针... p: - )

答案 1 :(得分:3)

这是一个功能声明。

int (*foo(bool))(int);

如果你想声明一个函数指针,你应该这样做:

int (*(*foo)(bool))(int);

答案 2 :(得分:0)

#include <stdlib.h>
#include <stdbool.h>

int inc(int i) { return i+1; }  // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  int (*(*foo)(bool))(int);  // foo is &(bool→(int→int))
  foo = baz;
  return 0;
}

因此,有一些副问题使核心问题蒙上阴影。您的“bool”被解释为默认 - int无类型参数,因为实际的内置函数是_Bool,由之前缺少的#include <stdbool.h>人性化。缺少堆栈上对象的指针声明使其能够符合上面静态存储器中实际函数对象的类型。

一旦我加入<stdbool.h>,错误就会转移到“lvalue required”投诉,因为只有一个函数声明而不是指针对象。上面的代码将编译时没有任何警告或错误。

答案 3 :(得分:0)

很难确定,但我认为这更接近于OP的意图:

// baz is a function returning a pointer to a function
int (*baz(bool b))(int) { return b ? &abs : &inc; }

int main() {
  // foo is a pointer to a function
  int (*foo)(int) ;
  foo = baz(true); // Now foo is equal to &abs
}

答案 4 :(得分:0)

你不能分配到函数类型(int (*foo(bool))(int);),你需要使用指向函数的指针

int (*(*foo)(bool))(int);
foo = &baz;
相关问题