【问题标题】:Redeclaring variables in C在 C 中重新声明变量
【发布时间】:2017-02-02 03:10:07
【问题描述】:

我看到过一个类似的问题问 wrt c++,Does redeclaring variables in C++ cost anything?

但是 C 呢?在 C 中重新声明变量会产生明显的影响吗?这通常被认为是糟糕的代码组织吗?

for(;;) {
   int y = 1 + 2 + 3; // some kind of repeated redeclaration? 
}

编辑:

加强我的提问。

如果我在函数中有一个循环,会调用'int y = 1 + 2 + 3;'一遍又一遍地被允许?会不会造成问题?有什么作用,声明一次y

【问题讨论】:

  • 不清楚你在问什么。如果您的问题是在循环中声明 int y 是否比在循环外花费更多 - 不,它没有。
  • @CinCout 当然可以。
  • 改进了我的问题。
  • 您的问题示例中没有不允许的重新声明,因为只有一个声明开头。我怀疑你的问题实际上更多的是关于 scope 而不是性能。
  • 我认为我在编辑中的要求非常清楚。当该特定行在循环中被调用时会发生什么,第一次和随后的时间。

标签: c


【解决方案1】:

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
}

这是无效的:

if(...) {
    int y;
    int y; # error, redeclaration
}

另外声明是源代码属性,不是运行时程序属性。

所以,如果你写:

for(;;) {
   int y = 1 + 2 + 3;
}

你声明y一次(因为你写过一次),而不是无限次。

【讨论】:

    【解决方案2】:

    大多数 C 编译器会尽可能优化所有内容。

    如果您想真正了解使用标志进行编译以查看汇编代码并查看它在做什么。就像有人说的那样,如果它是一个简单的类型(没有构造函数),特别是如果你使用所有文字,编译器可能只会在每次迭代时将一个固定值移动到一个寄存器中,或者即使没有任何改变也不会打扰迭代之间的变量

    我刚刚检查了您的示例如下所示,并且还对其进行了更改以修改循环中的变量,您可以看到汇编代码如何生成更改。

    在第一个例子中,注意 LBB0_1 处的循环,它只是一条 movl 指令。

    在第二个示例中,它仍然非常简单,但是即使没有使用结果,它仍然会将内容保存在堆栈中。我添加了一些 cmets 来解释循环在做什么。

    $ cc -fno-asynchronous-unwind-tables -S dummy.c

    int main(void) { 
        for(;;) {
            int y = 1 + 2 + 3;
        }
    }
    

    $ 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
    

    $ cc -fno-asynchronous-unwind-tables -S dummy.c

    int main(void) { 
        int i = 0;
        for(;;) {
            int y = i + 2 + 3;
            i++;
        }
    }
    

    $ 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
    

    【讨论】:

    • 谢谢 - 这对知道如何做非常有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多