int(*)(int *)= 5(或任何整数值)的含义
我无法弄清楚这一点:
int main() { int (*) (int *) = 5; return 0; }
上面的任务用g ++ c ++ 11编译。 我知道int (*) (int *)
是一个函数的指针,它接受一个(int *)
作为参数,并返回一个int,但我不明白你怎么可以将它等于5.起初我以为它是一个不断返回5的函数(从我最近学习的F#中,可能是哈哈),然后我简单地想,函数指针指向内存位置5,但是这不起作用,很明显,也不是hex值。
认为这可能是因为该函数返回一个int,并分配一个int是好的(不知何故),我也试过这个:
int * (*) (int *) = my_ptr
其中my_ptr
的types为int *
,与第二个函数指针的types相同,如第一种情况下的types为int。 这不会编译。 赋值5或者任何int值,而不是my_ptr
,也不会为这个函数指针编译。
那么这个任务是什么意思?
更新1
我们已经确认这是一个错误,如最佳答案所示。 但是,我们仍然不知道实际发生的情况是您分配给函数指针的值是什么,或者赋值时发生了什么。 任何(好)的解释,将非常感激! 请参阅下面的编辑,以更清楚地了解这个问题。
编辑1
我使用的是gcc版本4.8.2(在Ubuntu 4.8.2中)
编辑2
其实,把它等同于我的编译器。 即使将它等同于一个std :: stringvariables,或者返回一个double的函数名也是可行的。
编辑2.1
有趣的是,把它作为函数指针指向任何返回不是指针的数据types的函数,都会让它编译,比如
std::string (*) () = 5.6;
但是,只要函数指针指向一个返回某个指针的函数,它就不会编译,如
some_data_type ** (*) () = any_value;
这是g ++中的一个bug。
int (*) (int *)
是一个types名称。
在C ++中,不能使用没有标识符的types名称进行声明。
所以这个编译与g ++。
int (*) (int *) = 5;
这也编译:
int (*) (int *);
但他们都是无效的声明。
编辑 :
TC在评论bugzilla错误60680中提到了类似的testing用例, 但尚未获得批准 。 这个bug在bugzilla中得到确认。
编辑2 :
当上述两个声明在文件范围内时,g ++正确地发出一个诊断(它不能在块范围发出诊断)。
编辑3 :
我检查了一下,我可以在最新版本的g ++版本4(4.9.2),最新的预发布版本5(5.0.1 20150412)和最新的实验版本6(6.0.0 20150412)上重现这个问题。
这是无效的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 ++。 它声称是一个任务(因为=
),但不包含标识符。
正如其他答案已经指出,这是一个错误
int (*) (int *) = 5;
编译。 这个陈述的合理近似值可能会有一个含义:
int (*proc)(int*) = (int (*)(int*))(5);
现在, proc
是一个指向函数的指针,它要求地址5
是一个函数的基地址,它接受一个int*
并返回一个int
。
在一些微控制器/微处理器5
可能是有效的代码地址,并且可能在那里定位这样的function。
在大多数通用计算机上,为了捕获null
指针访问,内存的第一页(4K页面的地址0-1023
)被故意无效(未映射)。
因此,当行为取决于平台时,可以合理地期望在调用*proc
时发生页面错误(例如(*proc)(&v)
)。 在*proc
被调用之前,没有什么不寻常的事情发生。
除非你正在编写一个dynamic连接器,否则你几乎肯定不应该用数值计算地址,并把它们分配给指向函数的variables。
/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 } ...
这仍然不能回答究竟发生了什么,但它应该是朝着正确的方向迈出的一步。