我无法弄明白:
int main() {
int (*) (int *) = 5;
return 0;
}
上面的作业用g ++ c ++ 11编译。我知道int (*) (int *)
是一个指向函数的指针,该函数接受(int *)
作为参数并返回一个int,但我不明白你怎么能把它等同于5.起初我认为它是一个函数不断返回5(从我最近在F#中学习,可能,哈哈),然后我简单地想,函数指针指向内存位置5,但这不起作用,显然,也不是十六进制值。
认为这可能是因为函数返回一个int,并且分配一个int是好的(不知何故),我也试过了:
int * (*) (int *) = my_ptr
其中my_ptr
的类型为int *
,与第二个函数指针的类型相同,如第一种类型为int的情况。这不编译。分配5或任何int值而不是my_ptr
,也不会为此函数指针编译。
那么作业是什么意思?
更新1
我们已确认这是一个错误,如最佳答案所示。但是,仍然不知道实际发生到您分配给函数指针的值,或者赋值时会发生什么。任何(好的)解释都将非常感谢!有关问题的详细说明,请参阅下面的编辑。
修改1
我正在使用gcc版本4.8.2(在Ubuntu 4.8.2中)
修改2
实际上,将它等同于我的编译器。即使将它等同于std :: string变量,或者返回double的函数名,也可以。
编辑2.1
有趣的是,将它作为一个函数指针指向任何返回不是指针的数据类型的函数,都会让它编译,例如
std::string (*) () = 5.6;
但是只要函数指针指向返回某个指针的函数,它就不会编译,例如
some_data_type ** (*) () = any_value;
答案 0 :(得分:60)
这是g ++中的一个错误。
int (*) (int *)
是类型名称。
在C ++中,你不能拥有一个没有标识符的类型名称的声明。
所以这用g ++编译。
int (*) (int *) = 5;
并且这也编译:
int (*) (int *);
但它们都是无效的声明。
编辑:
T.C.在评论bugzilla bug 60680中提及类似的测试用例,但尚未获得批准。臭虫在bugzilla中得到证实。
<强> EDIT2 强>:
当上述两个声明位于文件范围时,g ++正确发出诊断(它无法在块范围内发出诊断)。
<强> EDIT3 强>:
我检查过,我可以在最新版本的g ++版本4(4.9.2),最新的预发行版本5(5.0.1 20150412)和最新的实验版本6(6.0.0 20150412)上重现该问题。< / p>
答案 1 :(得分:27)
它不是有效的C ++。请记住,因为您的特定编译器恰好编译它并不能使它有效。与所有复杂软件一样,编译器有时会出现错误,这似乎是一个错误。
相比之下clang++
抱怨:
funnycast.cpp:3:11: error: expected expression
int (*) (int *) = 5;
^
funnycast.cpp:3:18: error: expected '(' for function-style cast or type construction
int (*) (int *) = 5;
~~~ ^
funnycast.cpp:3:19: error: expected expression
int (*) (int *) = 5;
^
3 errors generated.
这是预期的行为,因为违规行不是有效的C ++。它声称是一个赋值(因为=
),但不包含标识符。
答案 2 :(得分:9)
正如其他答案所指出的,这是一个错误
int (*) (int *) = 5;
编译。预期具有含义的该陈述的合理近似是:
int (*proc)(int*) = (int (*)(int*))(5);
现在proc
是一个指向函数的指针,它希望地址5
是一个函数的基地址,它接受int*
并返回int
。
在某些微控制器/微处理器上5
可能是有效的代码地址,并且可能在那里找到这样的函数。
在大多数通用计算机上,内存的第一页(4K页面的地址0-1023
)故意无效(未映射),以便捕获null
指针访问。
因此,虽然行为取决于平台,但可以合理地预期在调用*proc
时发生页面错误(例如,(*proc)(&v)
)。在调用*proc
之前,没有任何异常发生。
除非您正在编写动态链接器,否则您几乎肯定不应该在数字上计算地址并将它们分配给指针到函数变量。
答案 3 :(得分:3)
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp
此命令行生成许多中间文件。其中第一个so.cpp.170r.expand
说:
...
int main() ()
{
int D.2229;
int _1;
;; basic block 2, loop depth 0
;; pred: ENTRY
_1 = 0;
;; succ: 3
;; basic block 3, loop depth 0
;; pred: 2
<L0>:
return _1;
;; succ: EXIT
}
...
这仍然无法回答究竟发生的事情,但它应该是朝着正确方向迈出的一步。