-- TOC --
从最早的C89开始,C语言就有一个特性,即在一个独立的block范围内,可以申明与block外同名的变量,此变量独立,不与block外的冲突。示例如下:
#include <stdio.h>
int main(void) {
int a = 1;
{
int a = 2;
printf("inside a = %d\n", a);
}
printf("outside a = %d\n", a);
return 0;
}
输出:
inside a = 2
outside a = 1
当一个独立的block范围需要重复执行的时候,就出现了(正常的)重复定义。请看下面代码:
#include <stdio.h>
#include <unistd.h>
int main(void) {
int a = 0;
while (1) {
int a = 1; // !!
a += 1;
printf("%d %p\n", a, &a);
sleep(1);
}
return 0;
}
int a = 1
在循环中不断地重复,其实,这种情况,不是redefinition!。以上代码可以正常编译执行:
$ gcc -Wall -Wextra test.c -o test
$ ./test
2 0x7fff13df446c
2 0x7fff13df446c
2 0x7fff13df446c
编译正常,变量a的地址在循环过程中保持不变,应该就不存在影响效率的问题了,但每次都会被重新赋值为1。
印象中,C语言是从C99开始,允许函数中的变量可以不在函数开始的位置统一申明和定义。这就给上述代码结构(我很喜欢这种结构,可随时根据代码的局部需要定义变量,可读性也更好,因为相关的代码可以尽可能放在一起)提供了更多的可行性。但独立block范围内的同名变量的相互独立,这个feature,是C89就开始有的。
下面这种情况,也属于在独立范围内定义变量:
#include <stdio.h>
#include <unistd.h>
int main(void) {
for (int i=0; i<4; ++i)
printf("%d", i);
for (int i=0; i<4; ++i) // int declare is must
printf("%d", i);
printf("\n");
return 0;
}
每个for loop中的变量i,都属于独立范围内定义的,第2个for里的i,如果去掉int申明,编译会报错,提示i未定义。
C++中的对象,也可以在独立范围内(重复)定义:
默念咒语:变量就是有名称的对象!...
#include <string>
#include <iostream>
#include <unistd.h>
using namespace std;
struct xyz {
xyz() {
cout << "..1..\n";
}
~xyz() {
cout << "..2..\n";
}
};
int main(void) {
while(1){
xyz x{};
sleep(1);
}
return 0;
}
以上代码输出:
..1..
..2..
..1..
..2..
..1..
..2..
...
通过打印可以看到,当独立block范围结束的时候,对象会被销毁,然后再进入独立block范围时,再被重建。
代码写成下面这样,也是OK的,对象会被正常销毁,然后重新创建:
#include <string>
#include <iostream>
#include <unistd.h>
using namespace std;
struct xyz {
xyz() {
cout << "..1..\n";
}
~xyz() {
cout << "..2..\n";
}
};
int main(void) {
while(1){
xyz x{};
if (true)
sleep(1);
continue;
sleep(1);
}
return 0;
}
编译器能够判断出,当continue时,这个独立范围的一次迭代就执行结束了,开始下一个迭代。
C++支持在if语句和switch语句中申明对象
请看代码:
#include <stdio.h>
int main(void) {
// redefinition error
//int i=0;
//int i=1;
if (int i=0; i!=0) {
// scope of zero i
printf("i is zero\n");
}
else if (int i=1; i==1) {
// scope of one i
printf("i is one\n");
}
return 0;
}
这段代码,gcc不能编译,但g++就可以正常编译。
据教材上说,这个用法与C++的Structured Binding结合起来,代码看起来非常nice!
下面是switch语句的测试:
#include <stdio.h>
int main(void) {
switch (int i=9; i) {
case 1:
printf("no..\n");
break;
case 9:
printf("yes..\n");
break;
}
return 0;
}
只有g++能编译!
本文链接:https://cs.pynote.net/sf/c/202210241/
-- EOF --
-- MORE --