【问题标题】:Is this function call "delay+(1000)" syntactically correct?这个函数调用“delay+(1000)”在语法上是否正确?
【发布时间】:2019-10-23 23:46:29
【问题描述】:

我正在编写一个小代码以在传感器读数高于某个阈值时启用蜂鸣器。为了让蜂鸣器保持一秒钟,我通过调用这个函数给出了 1000 毫秒的延迟:delay(1000)。但是,我随机输入了delay+(1000),它编译得很好。这个函数调用语法正确吗?

我已在 Arduino IDE 上尝试过此代码。它可以编译,但对于 avr-gcc 或 avr-g++ 或 gcc/g++ 而言,情况并非如此。

我希望 delay+(1000) 无法编译,因为它似乎不是有效的 c/c++ 语法。

更新 1:

使用Arduino IDE编译并上传以下代码sn-p到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: 错误:'void(long unsigned int)' 和 >'int' 类型的无效操作数到二进制 'operator*'

     delay*(1000);
               ^

但是,这个int t = (int)delay*(1000); 编译得很好。

更新 2:

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

我使用了以下代码sn-p:

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

它编译得很好,什么也不输出。

更新 3:

我在 Arduino IDE 的首选项下将编译器警告级别更改为“全部”。关于这个sn-p的编译,

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

获得以下警告:

sketch_jun09a.ino:在函数“void setup()”中: sketch_jun09a.ino:3:14:警告:指向算术中使用的函数的指针 [-Wpointer-arith]

  delay+(1000);
             ^

sketch_jun09a.ino:3:8: 警告:语句无效[-Wunused-value]

  delay+(1000);
       ^

【问题讨论】:

  • 它看起来像是通过将1000 添加到delay 来进行指针运算,然后丢弃结果(除非您将其分配给某物)。我不知道为什么它允许这样做,我无法想象它会有什么用处。
  • 标准 C 和标准 C++ 都不允许函数指针算术。然而,GCC 似乎有一个扩展。您应该调整编译标志,直到这成为编译器错误。
  • @chris:我给你一些关于扩展的格言。
  • @chris 我认为没有简单的方法可以在 arduino IDE 中调整编译标志。

标签: c++ c arduino-ide


【解决方案1】:

我认为它会将1000 添加到delayfunction pointer变量、常量或宏扩展,但表达式delay+(1000) 不行很多本身...

【讨论】:

    【解决方案2】:

    所以这里发生了两件事。

    delay+(1000)
    

    是将函数指针延迟加 1000 的语法。这当然是完全没有意义的,但它为什么要编译。通常您可以将整数添加到指针,但这不适用于void * 指针和函数指针。然而gcc 有一个扩展,通过将voidvoid() 类型的大小设置为1,可以添加到void *void(*)()。因此,向函数添加整数是可行的(无用的)。

    事实证明,将整数添加到void * 指针有时是您真正想要做的事情,并且扩展程序摆脱了一些烦人的额外局部变量,但函数指针几乎从来没有那样工作。我想不久前有人在构建 asm 代码,因为这是我能想象的唯一用例。提示:在某些架构上,函数指针不指向函数代码,而是指向描述符。

    【讨论】:

      【解决方案3】:

      查看 Joshua 的回答,了解原因。这是一个很好的答案。至于如何,你需要实际致电delay

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多