【问题标题】:Static variable in 'for' loop initial declaration“for”循环初始声明中的静态变量
【发布时间】:2014-01-14 18:37:36
【问题描述】:

想知道为什么我不能在for循环初始化中声明一个静态变量,如下所示,

for(static int i = 0;;)

用我的C99标准编译器编译上面的循环语句代码我看到了下面的错误,

error: declaration of static variable ‘i’ in ‘for’ loop initial declaration

【问题讨论】:

  • 因为语言不允许?这在什么情况下有用?
  • 每当我遇到这样的“奇怪”错误信息时,我都喜欢思考。在某些时候,事实总是证明,如果某事是不允许的,那么它就是不允许的——通常是因为它没有意义(如本例所示)。
  • @OliCharlesworth:虽然我同意这是没有意义的,并且该语言不应该/不允许这样做,但我实际上在 C99 中找不到任何明确禁止这样做的文本。 §6.2.2、§6.2.4、§6.7.1 和 §6.8.5.3 均未提及对 for 循环 AFAICT 的 clause-1 声明的任何限制。
  • @OliCharlesworth 啊实际上它在 §6.8.5 的顶部,我不知何故错过了(感谢@Chux!)
  • @OliCharlesworth 在for 循环内我有一个带有索引为[0, Size-1] 的数据包数据的圆环,应该通过环按顺序读取。所以我尝试声明静态,因为我的函数被每个数据包调用。我知道在for 之外声明它会对我有所帮助。

标签: c static c99


【解决方案1】:

C 不允许

C11dr 6.8.5 迭代语句 3

for 语句的声明部分只能声明具有存储类 autoregister 的对象的标识符”。

(不是static


通常代码不会使表单能够拥有static 的迭代器。


存储类说明符:

typedef
extern
static
_Thread_local
auto
register

【讨论】:

  • @SunEric T' 是一个有趣的帖子。以前从未尝试过 static 迭代器。根据您上面的评论,人们可以很容易地绕过它(“在外面声明它”)。我怀疑尝试使用 static 迭代器的原因可能会产生意想不到的副作用(re: re-entrantcy and others` posts),因此排除了这种方法。祝你好运。
【解决方案2】:

for 声明中声明变量的目的是将其范围缩小到循环块。

// i does not exist here
for (int i = 0;;) {
  // i exists here
}
// i does not exist here

当您将局部变量声明为static 并对其进行初始化时,初始化仅在代码首次运行时进行一次。

{
  static int i = 0; // i will be set to 0 the first time this is called
  i++;
}

因此,在循环声明中初始化的带有static 变量的for 循环只会被初始化一次!

// i will not be initialized to 0 the second time this loop runs and we cannot
// initialize it here, before the loop block
for (static int i = 0;;) {
  // ...
}

【讨论】:

    【解决方案3】:

    实际上,这可以在 g++ 4.4.3 中按预期编译和工作。

    #include <stdio.h>
    
    #define LOG() testPrintfPtr
    #define LOG_ONCE() \
        for (static bool __only_once_ = 0; !__only_once_; __only_once_ = true) \
            LOG()
    
    struct test {
        void debug(const char *str) {
            printf("%s\n", str);
        }
    };
    
    test *testPrintfPtr = new test();
    
    int main() {
        for (int i = 0; i < 10; ++i)
            LOG_ONCE()->debug("ciao 1");
    
        LOG_ONCE()->debug("ciao 2");
    
        return 0;
    }
    

    目的是为日志 API(其入口点由 LOG() 宏全局提供)提供无缝包装,以便该日志行在程序的生命周期内仅执行一次。

    执行程序会得到以下结果:

    $ ./testLogOnce
    ciao 1
    ciao 2
    

    我假设 C++ 标准允许这样做?

    【讨论】:

      【解决方案4】:

      你想完成什么?

      如果您试图在for 循环之外访问变量i,则必须在for 循环之外声明它:

      int i;
      for(i = 0; ; )
      {
          …
      }
      printf("%d\n", i);
      

      如果您想让for 循环仅在第一次调用函数时执行,请创建一个static 布尔变量来处理它。

      static bool firstTime = true;
      
      if(firstTime)
      {
          for(int i = 0; ; )
          {
              …
          }
      
          firstTime = false;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-07
        • 1970-01-01
        • 2013-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多