带正方形括号的c ++函数调用

San*_*Pal 15 c++ c++14

int func(int n)
{return n;}

int main()
{ cout << func[4] ;
cout << func[4,3,5] ;}
Run Code Online (Sandbox Code Playgroud)

这些实际意味着什么?我想它是关于访问func + 4和func在调用func [4]上分配空间.但是,func [4,3,5]是荒谬的.

Chr*_*eck 15

此代码编译并且func[4]不是语法错误的原因是:

1.函数类型可以隐式转换为相同类型的指针.所以,如果我们有这样的代码:

int f(int);

using func_t = int(*)(int);

void g(func_t);
Run Code Online (Sandbox Code Playgroud)

我们可以写

g(f)
Run Code Online (Sandbox Code Playgroud)

并没有被迫写g(&f).的&,从类型带我们int(int)int(*)(int)隐式发生.

2.In C(并且必须在C++中用于兼容性)指针连接到数组,并且p指针何时与指针p[x]相同*(p + x).所以func[4]是一样的*(func + 4).

3. *(p+x)具有函数的类型int(int),但在必要时也可以隐式地衰减为指针类型.所以*(func + 4)可以隐含的只是(func + 4).

4.任何类型的打印机都可以流式传输std::cout.


请注意,仅仅因为它不是语法错误并不意味着它是有效的.当然它是未定义的行为,并且由gcc和clang发出的编译器警告指示,带有函数指针的指针算法一般是错误的,因为你不能创建一个函数数组.该实现放置了它喜欢的功能.(你可以创建一个函数指针数组,但这完全不同.)


编辑:我应该纠正自己 - 这个答案并不完全正确.func[4]无效,因为指针不是指向对象类型的指针.@holyblackcat的回答是正确的,请参阅他的答案以供参考.

此代码应该是格式错误的,并且gcc仅编译它而没有错误,因为它们默认使用非标准扩展.Clang和msvc正确拒绝此代码.


Hol*_*Cat 10

我很惊讶没有回答提到它,但是:

问题中的代码根本不是有效的C++.

它被Clang和MSVC 拒绝,没有标志.海湾合作委员会拒绝接受-pedantic-errors.

a[b](在没有运算符重载的情况下)定义为*(a + b),并且内置运算符+要求指针操作数是指向对象类型的指针(函数指针不是).

[expr.add]/1

...两个操作数都应具有算术或无范围的枚举类型,或者一个操作数应是指向完全定义的对象类型的指针,另一个操作数应具有整数或无范围的枚举类型.

(强调我的.)


GCC编译代码,因为默认情况下启用允许对函数指针进行算术运算的扩展.

由于函数到指针的衰减,func[4]被视为&(&func)[4]有效地意味着&func + 4(如链接所解释的)简单地添加4到指针的数值.调用结果指针很可能会导致崩溃或不可预测的结果.

std::cout没有<<适合打印函数指针的重载,编译器能够找到的最合适的重载是打印bools.指针被转换为bool,因为它是非空的,它变为true,然后打印为1.

最后,func[4,3,5]具有相同的效果func[5],因为在此上下文中,被视为运算符,并且x , y等于y.


Max*_*hof 5

由于尚未提及:func[3, 4, 5]func[5]-相同的逗号是内置的逗号运算符,它计算左侧表达式,丢弃它,然后计算右侧表达式。这里没有发生函数调用,代码中的逗号也没有分隔函数参数。


Siv*_*h B 3

是的,它是关于访问func+4尚未定义的,导致垃圾值。因此编译器会向您显示以下警告消息。

hereProgram: In function 'int main()':
Program:7: warning: pointer to a function used in arithmetic
Run Code Online (Sandbox Code Playgroud)