带有方括号的c ++函数调用

时间:2018-10-08 06:03:51

标签: c++ c++14

int func(int n)
{return n;}

int main()
{ cout << func[4] ;
cout << func[4,3,5] ;}

这些实际上是什么意思?我想这与访问func + 4有关,并且func在调用func [4]时分配了空间。 但是,func [4,3,5]只是荒谬的。

4 个答案:

答案 0 :(得分:15)

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

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

int f(int);

using func_t = int(*)(int);

void g(func_t);

我们可以写

g(f)

,并且不会被迫写g(&f)&使我们从类型int(int)int(*)(int)隐式发生。

2。在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正确拒绝了此代码。

答案 1 :(得分:10)

我很惊讶没有任何提及,但是:

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

它是Clang和MSVC的rejected,没有标志。 GCC用-pedantic-errors拒绝了它。

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

  

[expr.add]/1

     

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

(强调我的。)


GCC编译代码,因为默认情况下启用了an extension allowing arithmetic on function pointer

由于函数到指针的衰减,func[4]被视为&(&func)[4],实际上是指&func + 4,它(如链接所述)仅将4添加到指针的数值。调用结果指针很可能会导致崩溃或结果异常。

std::cout没有适合打印函数指针的<<重载,并且编译器能够找到的最适合的重载是打印bool的重载。指针将转换为bool,由于它不是空值,因此变为true,然后将其打印为1

最后,func[4,3,5]func[5]具有相同的效果,因为在这种情况下,被视为运算符,并且x , y等于y

答案 2 :(得分:4)

由于尚未提及它:func[3, 4, 5]func[5]相同-内置的逗号comma operator用于评估左侧表达式,将其舍弃然后求值右边的表情。这里没有发生函数调用,并且代码中的逗号不是分隔函数参数的地方。

答案 3 :(得分:3)

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

hereProgram: In function 'int main()':
Program:7: warning: pointer to a function used in arithmetic