哪里可以而且不能在C中声明新变量?

Dan*_*cco 73 c declaration

我听说(可能来自老师)应该在程序/函数之上声明所有变量,并且在语句中声明新变量可能会导致问题.

但后来我正在阅读K&R,我发现了这句话:"变量的声明(包括初始化)可能会在左括号后面引入任何复合语句,而不仅仅是开始函数的语句".他举了一个例子:

if (n > 0){
    int i;
    for (i=0;i<n;i++)
    ...
}
Run Code Online (Sandbox Code Playgroud)

我玩了一下这个概念,它甚至可以用于数组.例如:

int main(){
    int x = 0 ;

    while (x<10){
        if (x>5){
            int y[x];
            y[0] = 10;
            printf("%d %d\n",y[0],y[4]);
        }
        x++;
    }
}
Run Code Online (Sandbox Code Playgroud)

那么当我不允许声明变量时呢?例如,如果我的变量声明不在开括号之后呢?像这儿:

int main(){
    int x = 10;

    x++;
    printf("%d\n",x);

    int z = 6;
    printf("%d\n",z);
}
Run Code Online (Sandbox Code Playgroud)

这可能导致麻烦,具体取决于程序/机器吗?

hug*_*omg 116

我也经常听到将变量置于函数顶部是做事的最佳方式,但我强烈反对.我更喜欢将变量限制在可能的最小范围内,因此它们被滥用的机会较少,因此我在程序的每一行中填充心理空间的东西较少.

虽然所有版本的C都允许使用词法块作用域,但您可以声明变量取决于您所定位的C标准版本:

C99以后或C++

现代C编译器(如gcc和clang)支持C99C11标准,这些标准允许您在语句的任何位置声明变量.变量的范围从声明点开始到块的结尾(下一个右括号).

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line
   int z = 42;
   printf("%d", z);   // z is in scope in this line
}
Run Code Online (Sandbox Code Playgroud)

您还可以在for循环初始化器中声明变量.该变量仅存在于循环内部.

for(int i=0; i<10; i++){
    printf("%d", i);
}
Run Code Online (Sandbox Code Playgroud)

ANSI C(C90)

如果您的目标是旧的ANSI C标准,那么您只能在开始括号1之后立即声明变量.

这并不意味着您必须在函数顶部声明所有变量.在C语言中,你可以在一个语句的任何地方放置一个大括号分隔的块(不仅仅是在if或之后for),你可以使用它来引入新的变量作用域.以下是以前C99示例的ANSI C版本:

if( x < 10 ){
   printf("%d", 17);  // z is not in scope in this line

   {
       int z = 42;
       printf("%d", z);   // z is in scope in this line
   }
}

{int i; for(i=0; i<10; i++){
    printf("%d", i);
}}
Run Code Online (Sandbox Code Playgroud)

1请注意,如果您正在使用gcc,则需要传递该--pedantic标志以使其实际执行C90标准并抱怨变量在错误的位置声明.如果你只是使用-std=c90它使得gcc接受C90的超集,这也允许更灵活的C99变量声明.

  • @underscore_d请记住,想要节省内存的人经常处理嵌入式系统,其中一个被迫坚持较低的优化级别和/或较旧的编译器版本,因为认证和/或工具链方面. (3认同)
  • “变量的范围从声明点开始到块的末尾” - 如果有人想知道,这并不意味着手动创建较窄的块对于使编译器有效地使用堆栈空间有用/需要。我已经见过几次这样的情况了,这是从错误的说法中得出的错误推论,即 C 是“可移植汇编程序”。因为 (A) 变量可能分配在寄存器中,而不是堆栈上,&amp; (B) 如果变量位于堆栈上但编译器可以看到您停止使用它,例如在块中使用了 10%,则它可以轻松地回收该空间以用于其他用途。 (2认同)
  • 我不知道你从哪里得到的想法是,在范围中间声明变量只是“有效地将声明移到顶部的黑客”。情况并非如此,如果您尝试在一行中使用变量并在下一行中声明它,您将收到“变量未声明”编译错误。 (2认同)