我已经看到了一个类似的问题wrt c ++,在C++中重新声明变量会花费什么吗?
但是C怎么样?在C中重新声明变量会有任何明显的影响吗?这通常被认为是不良的代码组织吗?
for(;;) {
int y = 1 + 2 + 3; // some kind of repeated redeclaration?
}
Run Code Online (Sandbox Code Playgroud)
编辑:
加强我的要求.
如果我在函数中有一个循环,则会调用'int y = 1 + 2 + 3;' 一遍又一遍被允许?它会引起问题吗?它做了什么,宣布y一次?
C语言具有可变范围的概念.简而言之,每对{和}引入新范围,变量都绑定到那些范围.您可以声明具有相同名称的变量,只要它们位于不同的范围内即可.
这就是你有效的原因:
if(...) {
int y; # y is valid here
} # end of scope, y is not valid here
if(...) { # new scope
int y; # That's another y
}
Run Code Online (Sandbox Code Playgroud)
那是无效的:
if(...) {
int y;
int y; # error, redeclaration
}
Run Code Online (Sandbox Code Playgroud)
而且声明是源代码属性,而不是运行时程序属性.
所以,如果你写:
for(;;) {
int y = 1 + 2 + 3;
}
Run Code Online (Sandbox Code Playgroud)
你声明y 一次(因为你已经写过一次),而不是无限次.
大多数C编译器都会尽可能地优化所有内容.
如果你想真正找到带有标志的编译来查看汇编代码并看看它在做什么.就像有人说如果它是一个简单类型(没有构造函数),特别是如果你使用所有文字,编译器可能只是在每次迭代时将固定值移动到寄存器中,或者如果没有任何改变则甚至不会打扰迭代之间的变量
我刚刚检查了您的示例,如下所示,并且还更改了它以修改循环中的变量,您可以看到生成的汇编代码如何更改.
在第一个例子中,注意LBB0_1的循环,它只是一个movl指令.
在第二个例子中,它仍然非常简单,但即使没有使用结果,它仍然可以节省堆栈中的内容.我添加了一些注释来解释循环正在做什么.
$ cc -fno-asynchronous-unwind-tables -S dummy.c
int main(void) {
for(;;) {
int y = 1 + 2 + 3;
}
}
Run Code Online (Sandbox Code Playgroud)
$ cat dummy.s
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
## BB#0:
pushq %rbp
movq %rsp, %rbp
movl $0, -4(%rbp)
LBB0_1: ## =>This Inner Loop Header: Depth=1
movl $6, -8(%rbp)
jmp LBB0_1
.subsections_via_symbols
Run Code Online (Sandbox Code Playgroud)
$ cc -fno-asynchronous-unwind-tables -S dummy.c
int main(void) {
int i = 0;
for(;;) {
int y = i + 2 + 3;
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
$ cat dummy.s
.section __TEXT,__text,regular,pure_instructions
.macosx_version_min 10, 12
.globl _main
.align 4, 0x90
_main: ## @main
## BB#0:
pushq %rbp
movq %rsp, %rbp
movl $0, -4(%rbp)
movl $0, -8(%rbp) ## i = 0
LBB0_1:
movl -8(%rbp), %eax ## y = i
addl $2, %eax ## y += 2
addl $3, %eax ## y += 3
movl %eax, -12(%rbp) ## -12(rbp) = y
movl -8(%rbp), %eax ## eax = i
addl $1, %eax ## i++
movl %eax, -8(%rbp) ## -8(rbp) = i
jmp LBB0_1
.subsections_via_symbols
Run Code Online (Sandbox Code Playgroud)