在循环参数中初始化的变量范围是 C 中未定义的行为还是实现定义的行为?

问题描述 投票:0回答:2

就我今天所知,在 C 语言中,如果循环 for/while 有括号,它就有作用域,对吗?我在 GCC 中尝试了一些代码,情况似乎如此,例如:

for(unsigned char i=0;...;...){
   unsigned char j=0;
}
//Outside of the for scope:
unsigned char j=0;

这里我们完全没有问题,但是,循环参数内的变量呢?

例如,GBD C COMPILER(在线)中的这段代码:

switch(Maneral){
      case 1:
         for(unsigned char i=0x0A;i<=0x64;i=i+0x0A){
            indice++;
         }
      break;
      
      case 2:
         for(unsigned char i=0x0A;i<=0x64;i=i+0x0A){
            indice++;
         }
      break;
   }

没有给出错误,我认为它没有给出错误,因为在 for 'share' 的参数内初始化的变量各自 for 的括号的范围

至少直到今天这都是我的头炮,因为我正在使用 CCS C 编译器为 MCU 编写一些嵌入式代码;该编译器表示具有“97% ANSI C 兼容性”,在此编译器中,下一个代码:

switch(Maneral){
      case M_CONICO:
         for(unsigned char i=0x0A;i<=0x64;i=i+0x0A){ unsigned char too=0;
            ActualizaValor(i,DataConico[index]);
            index++;
         }
      break;
      
      case M_CHICO:
         for(unsigned char i=0x0A;i<=0x64;i=i+0x0A){ //LINE 'X'
            ActualizaValor(i,DataChico[index]);
            index++;
         }
      break;
   }

在“X”行上给出错误,它表示标识符已在此范围内使用,例如,如果我在第二个 for 循环中将“i”更改为“j”,则不会给出错误,对于声明的变量/在括号内定义(而不是在循环的参数中)它没有问题(CCS C 编译器)

因此,在“for()”这样的循环参数内初始化的变量的范围类似于实现定义的行为/未定义的行为,或者它是97% ANSI C 兼容性

提前致谢!

编辑:我知道我可以在开关之外声明/定义“i”,但我想理解这一点,因为我认为我确定我所知道的

c loops scope undefined-behavior
2个回答
0
投票

从 C99 开始,在

for
循环的 init 子句中声明的变量的作用域为 整个 循环,因此
for
循环的行为大致就像在其周围有一组额外的隐式大括号一样,例如:

for(unsigned char i=0;...;...){
   unsigned char j=0;
}

表现得就像您键入:

{
   unsigned char i=0
   for(;...;...){
       unsigned char j=0;
   }
}

但这是 C99(及更高版本)的功能,并且声称“ANSI C 兼容性”的内容可能指的是 C89/C90 标准,而

for
循环的此功能不是标准的一部分。


0
投票

C 2017 在 6.8.5.3p1 中说:

如果子句 1 是声明,则它声明的任何标识符的范围 是声明的剩余部分和整个循环,包括其他两个表达式;这是 在第一次计算控制表达式之前达到的执行顺序。如果子句-1 是一个表达式,在第一次评估控制之前,它被评估为 void 表达式 表达。

所以编译器过于热心了。

© www.soinside.com 2019 - 2024. All rights reserved.