这个函数调用"delay+(1000)"在语法上正确吗?

5
我正在编写一个小程序,当传感器读数超过一定阈值时,启用蜂鸣器。为了让蜂鸣器响铃1秒钟,我调用了这个函数:delay(1000)。然而,我随意输入了delay+(1000),它能够编译通过。这个函数调用语句在语法上是否正确?
我已经在Arduino IDE上尝试了这段代码。它可以编译,但是对于avr-gcc、avr-g++或gcc/g++来说不是这样的。
我预期delay+(1000)不能编译通过,因为它似乎不是有效的C/C++语法。 更新1: 使用Arduino IDE编译并上传了以下代码片段到Arduino UNO:
void setup() 
{
    Serial.begin(9600);
}

void loop()
{
    int x = delay+(1000);
    Serial.println(x);
}

它连续打印一个随机数1132,没有任何延迟。(所以,1132 => 函数指针地址 + 100?)

我还观察到delay+(1000)delay-(1000)可以编译通过,但对于delay*(1000)delay/(1000)则不是这样。编译器会输出以下错误:

sketch_jun09a:8: error: invalid operands of types 'void(long unsigned int)' and >'int' to binary 'operator*'

     delay*(1000);
               ^

然而,这个int t = (int)delay*(1000);编译成功。

更新2:

根据下面的答案,delay<operator>(x)只执行函数指针算术运算(使用一元或二元运算符),而不会执行函数本身。

我已经使用了以下代码片段:

void setup()
{
    Serial.begin(9600);
}
int custom()
{
    Serial.println("hello");
    return 0;
}
void loop()
{
    custom+(1000);
    delay+(1000);
}

它编译成功了,但没有输出。

更新3:

我在Arduino IDE的首选项下更改了编译器警告级别为“ALL”。在编译此片段时,

void setup() 
{
    delay+(1000);
}
void loop() {}

以下是获得的警告:

sketch_jun09a.ino: In function 'void setup()': sketch_jun09a.ino:3:14: warning: pointer to a function used in arithmetic [-Wpointer-arith]

  delay+(1000);
             ^

sketch_jun09a.ino:3:8: warning: statement has no effect [-Wunused-value]

  delay+(1000);
       ^

看起来它正在执行指针算术运算,通过将“delay”加上“1000”,然后丢弃结果(除非你将其分配给某个变量)。我不知道为什么它允许这样做,也无法想象它如何有用。 - Tom Karzes
标准的 C 和 C++ 都不允许函数指针算术运算。然而,GCC 似乎有一个扩展可以实现这个功能。你应该调整编译选项,直到它成为编译器错误。 - chris
@chris:我为这个扩展给你提供了一些准则。 - Joshua
@chris 我认为在Arduino IDE中调整编译标志没有简单的方法。 - the busybee
3个回答

9

这里有两件事情需要解决。

delay+(1000)

这段代码的语法是将 1000 加到函数指针 delay 上,这显然是没有任何意义的,但为什么它还能编译通过呢?通常情况下,你可以将整数加到指针上,但这不适用于 void * 指针和函数指针。然而,gcc 有一个扩展属性,使得对 void *void(*)() 的加法成立,原因是给 voidvoid() 类型分配了大小为 1 的空间。所以,向函数添加整数是有效的(虽然毫无意义)。

事实证明,有时你确实需要向 void * 指针添加整数,并且这个扩展功能可以消除一些烦人的额外局部变量,但函数指针几乎从不这样工作。我猜测有人在组装汇编代码,因为这是我能想象到的唯一用例。提示:在某些体系结构中,函数指针不指向函数代码,而是指向描述符。


2
我认为它会将delay的函数指针、变量、常量或宏扩展添加1000,但是delay+(1000)这个表达式本身并没有什么作用...最初的回答。

0

看 Joshua 的回答,他解释得非常好。至于该怎么,你需要实际调用delay函数。

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    delay(1000);
    Serial.println("Hi there");
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接