int (*) (int *) = 5(或任何整数值)的含义
Meaning of int (*) (int *) = 5 (or any integer value)
我想不通:
int main() {
int (*) (int *) = 5;
return 0;
}
以上作业使用 g++ c++11 编译。我知道 int (*) (int *)
是一个指向接受 (int *)
作为参数和 returns int 的函数的指针,但我不明白你怎么能把它等同于 5。起初我以为是一个不断returns5的函数(从我最近学习F#,大概,哈哈),然后我想,简单的说,函数指针指向内存位置5,但是这不起作用,很明显,并且十六进制值也没有。
认为可能是因为函数 returns 是一个 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 变量,或者一个 returns double 的函数名,也可以工作。
编辑 2.1
有趣的是,将其设为指向任何 returns 数据类型不是指针的函数的函数指针,将让它编译,例如
std::string (*) () = 5.6;
但是一旦函数指针指向returns某个函数的指针,它就不会编译,比如with
some_data_type ** (*) () = any_value;
这是 g++ 中的错误。
int (*) (int *)
是类型名称。
在 C++ 中,您不能使用没有标识符的类型名称进行声明。
所以这是用 g++ 编译的。
int (*) (int *) = 5;
这也可以编译:
int (*) (int *);
但它们都是无效的声明。
编辑:
T.C. mentions in the comments bugzilla bug 60680 具有类似的测试用例但尚未获得批准。该错误已在 bugzilla 中得到确认。
EDIT2:
当上面的两个声明在文件范围内时,g++ 会正确发出诊断(它无法在块范围内发出诊断)。
EDIT3:
我检查过,我可以在最新版本的 g++ 版本 4 (4.9.2)、最新的预发布版本 5 (5.0.1 20150412) 和最新的实验版本 6 (6.0.0 20150412) 上重现该问题.
/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
}
...
这仍然没有回答到底发生了什么,但它应该是朝着正确方向迈出的一步。
它不是有效的 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*
和 returns 的函数的基地址int
.
在某些 microcontrollers/microprocessors 上 5
可能是一个有效的代码地址,并且可能在那里找到这样的函数。
在大多数通用计算机上,内存的第一页(4K 页的地址 0-1023
)故意无效(未映射)以捕获 null
指针访问。
因此,虽然行为取决于平台,但可以合理地预期在调用 *proc
时会发生页面错误(例如,(*proc)(&v)
)。在调用 *proc
之前,没有任何异常发生。
除非您正在编写动态链接器,否则您几乎肯定不应该以数字方式计算地址并将它们分配给指向函数的指针变量。
我想不通:
int main() {
int (*) (int *) = 5;
return 0;
}
以上作业使用 g++ c++11 编译。我知道 int (*) (int *)
是一个指向接受 (int *)
作为参数和 returns int 的函数的指针,但我不明白你怎么能把它等同于 5。起初我以为是一个不断returns5的函数(从我最近学习F#,大概,哈哈),然后我想,简单的说,函数指针指向内存位置5,但是这不起作用,很明显,并且十六进制值也没有。
认为可能是因为函数 returns 是一个 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 变量,或者一个 returns double 的函数名,也可以工作。
编辑 2.1
有趣的是,将其设为指向任何 returns 数据类型不是指针的函数的函数指针,将让它编译,例如
std::string (*) () = 5.6;
但是一旦函数指针指向returns某个函数的指针,它就不会编译,比如with
some_data_type ** (*) () = any_value;
这是 g++ 中的错误。
int (*) (int *)
是类型名称。
在 C++ 中,您不能使用没有标识符的类型名称进行声明。
所以这是用 g++ 编译的。
int (*) (int *) = 5;
这也可以编译:
int (*) (int *);
但它们都是无效的声明。
编辑:
T.C. mentions in the comments bugzilla bug 60680 具有类似的测试用例但尚未获得批准。该错误已在 bugzilla 中得到确认。
EDIT2:
当上面的两个声明在文件范围内时,g++ 会正确发出诊断(它无法在块范围内发出诊断)。
EDIT3:
我检查过,我可以在最新版本的 g++ 版本 4 (4.9.2)、最新的预发布版本 5 (5.0.1 20150412) 和最新的实验版本 6 (6.0.0 20150412) 上重现该问题.
/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
}
...
这仍然没有回答到底发生了什么,但它应该是朝着正确方向迈出的一步。
它不是有效的 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*
和 returns 的函数的基地址int
.
在某些 microcontrollers/microprocessors 上 5
可能是一个有效的代码地址,并且可能在那里找到这样的函数。
在大多数通用计算机上,内存的第一页(4K 页的地址 0-1023
)故意无效(未映射)以捕获 null
指针访问。
因此,虽然行为取决于平台,但可以合理地预期在调用 *proc
时会发生页面错误(例如,(*proc)(&v)
)。在调用 *proc
之前,没有任何异常发生。
除非您正在编写动态链接器,否则您几乎肯定不应该以数字方式计算地址并将它们分配给指向函数的指针变量。