在C99中哪里可以合法地声明变量?

时间:2022-06-19 00:09:36

When I was first introduced to C I was told to always declare my variables at the top of the function. Now that I have a strong grasp of the language I am focusing my efforts on coding style, particularly limiting the scope of my variables. I have read about the benefits to limiting the scope and I came across an interesting example. Apparently, C99 allows you to do this...

当我第一次接触C时,我被告知总是在函数的顶端声明变量。既然我对这门语言有了很强的掌握,我就把精力集中在编码风格上,特别是限制了变量的范围。我读过限制范围的好处,我遇到了一个有趣的例子。显然,C99允许你这样做…

for (int i = 0; i < 10; i++)
{
   puts("hello");
}

I had thought that a variables scope was limited by the inner-most surrounding curly braces { }, but in the above example int i appears to be limited in scope by the curly braces of the for-loop even though it is declared outside of them.

我曾认为变量作用域受到最内部的花括号{}的限制,但是在上面的例子中,尽管for循环的花括号在它们之外声明,但在作用域中,我似乎受到了限制。

I tried to extend the above example with fgets() to do what I thought was something similar but both of these gave me a syntax error.

我试图用fgets()扩展上面的示例,以完成我认为类似的事情,但这两个都给了我一个语法错误。

fgets(char fpath[80], 80, stdin); *See Note**

80年fgets(char fpath[80],stdin);*注意* *

fgets(char* fpath = malloc(80), 80, stdin);

fgets(char* fpath = malloc(80), 80, stdin);

So, just where exactly is it legal to declare variables in C99? Was the for-loop example an exception to the rule? Does this apply to while and do while loops as well?

那么,在C99中声明变量究竟在哪里合法呢?for循环示例是规则的一个例外吗?这也适用于while循环吗?

*Note**: I'm not even sure this would be syntactically correct even if I could declare the char array there since fgets() is looking for pointer to char not pointer to array 80 of char. This is why I tried the malloc() version.

*注意*:我甚至不确定这是否语法正确,即使我可以在那里声明char数组,因为fgets()正在寻找指向char的指针,而不是指向char的80数组的指针。这就是我尝试malloc()版本的原因。

3 个解决方案

#1


32  

In C99, you can declare your variables where you need them, just like C++ allows you to do that.

在C99中,可以在需要的地方声明变量,就像c++允许的那样。

void somefunc(char *arg)
{
    char *ptr = "xyz";
    if (strcmp(arg, ptr) == 0)
    {
        int abc = 0;    /* Always could declare variables at a block start */

        somefunc(arg, &ptr, &abc);

        int def = another_func(abc, arg);   /* New in C99 */
        ...other code using def, presumably...
    }
}
  • You can declare a variable in the control part of a 'for' loop:

    可以在“for”循环的控制部分声明一个变量:

    for (int x = 0; x < 10; x++)    /* New in C99 */
    
  • You cannot declare a variable in the control part of a 'while' loop or an 'if' statement.

    不能在'while'循环或'if'语句的控件部分声明变量。

  • You cannot declare a variable in a function call.
  • 不能在函数调用中声明变量。
  • Obviously, you can (and always could) declare variables in the block after any loop or an 'if' statement.
  • 显然,您可以(而且总是可以)在任何循环或“if”语句之后在块中声明变量。

The C99 standard says:

C99标准说:

6.8.5.3 The for statement

6.8.5.3 for语句

The statement

该声明

for ( clause-1 ; expression-2 ; expression-3 ) statement

behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any variables it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.

行为如下:表达式表达式表达式表达式表达式表达式-2是在每次执行循环主体之前计算的控制表达式。expression-3表达式在循环体的每次执行之后被计算为void表达式。如果第1条是一个声明,那么它声明的任何变量的范围就是声明和整个循环的余数,包括其他两个表达式;在第一次对控制表达式进行评估之前,按执行顺序进行。如果clause-1是一个表达式,那么在第一次对控制表达式进行评估之前,它将被评估为一个无效表达式。

#2


8  

The first thing I'd note is that you shouldn't confuse

我要注意的第一件事是你不应该混淆

for (int i = 0; i < 10; i++) {
    puts("hello");
}

and

fgets(char* fpath = malloc(80), 80, stdin);

The first is a control structure while the second is a function call. The control structure evaluates the text inside it's parens() in a very different way from how a function call does.

第一个是控制结构,第二个是函数调用。控件结构以一种与函数调用完全不同的方式评估其parens()中的文本。

The second thing is... I don't understand what you're trying to say by:

第二件事是……我不明白你想说什么:

the compiler will promptly give you an error if you try to use i inside the for-loop body.

如果您试图在for循环主体中使用i,编译器将立即给您一个错误。

The code you listed for the for loop is a very common structure in C and the variable "i" should, indeed, be available inside the for loop body. Ie, the following should work:

您为for循环列出的代码是C中非常常见的结构,并且变量“i”应该在for循环体中可用。例如,以下方法应该有效:

int n = 0;
for (int i = 0; i < 10; i++) {
    n += i;
}

Am I misreading what you're saying?

我误解你的意思了吗?

#3


2  

The bottom line with respect to your for/fgets confusion is that while "enclosing braces control scope" is the correct rule in C most of the time, there is another rule regarding scope in C99 (borrowed from C++) that says that a variable declared in the prologue of a control structure (i.e. for, while, if) is in scope in the body of the structure (and is not in scope outside the body).

底线函数/困惑关于你的是,虽然“封闭括号控制范围”是正确的规则在C语言中大多数时候,C99中还有另一个规则关于范围(借用c++)说,序言中声明一个变量的控制结构(例如,如果是在范围的主体结构(并不是在身体以外的范围)。

#1


32  

In C99, you can declare your variables where you need them, just like C++ allows you to do that.

在C99中,可以在需要的地方声明变量,就像c++允许的那样。

void somefunc(char *arg)
{
    char *ptr = "xyz";
    if (strcmp(arg, ptr) == 0)
    {
        int abc = 0;    /* Always could declare variables at a block start */

        somefunc(arg, &ptr, &abc);

        int def = another_func(abc, arg);   /* New in C99 */
        ...other code using def, presumably...
    }
}
  • You can declare a variable in the control part of a 'for' loop:

    可以在“for”循环的控制部分声明一个变量:

    for (int x = 0; x < 10; x++)    /* New in C99 */
    
  • You cannot declare a variable in the control part of a 'while' loop or an 'if' statement.

    不能在'while'循环或'if'语句的控件部分声明变量。

  • You cannot declare a variable in a function call.
  • 不能在函数调用中声明变量。
  • Obviously, you can (and always could) declare variables in the block after any loop or an 'if' statement.
  • 显然,您可以(而且总是可以)在任何循环或“if”语句之后在块中声明变量。

The C99 standard says:

C99标准说:

6.8.5.3 The for statement

6.8.5.3 for语句

The statement

该声明

for ( clause-1 ; expression-2 ; expression-3 ) statement

behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any variables it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.

行为如下:表达式表达式表达式表达式表达式表达式-2是在每次执行循环主体之前计算的控制表达式。expression-3表达式在循环体的每次执行之后被计算为void表达式。如果第1条是一个声明,那么它声明的任何变量的范围就是声明和整个循环的余数,包括其他两个表达式;在第一次对控制表达式进行评估之前,按执行顺序进行。如果clause-1是一个表达式,那么在第一次对控制表达式进行评估之前,它将被评估为一个无效表达式。

#2


8  

The first thing I'd note is that you shouldn't confuse

我要注意的第一件事是你不应该混淆

for (int i = 0; i < 10; i++) {
    puts("hello");
}

and

fgets(char* fpath = malloc(80), 80, stdin);

The first is a control structure while the second is a function call. The control structure evaluates the text inside it's parens() in a very different way from how a function call does.

第一个是控制结构,第二个是函数调用。控件结构以一种与函数调用完全不同的方式评估其parens()中的文本。

The second thing is... I don't understand what you're trying to say by:

第二件事是……我不明白你想说什么:

the compiler will promptly give you an error if you try to use i inside the for-loop body.

如果您试图在for循环主体中使用i,编译器将立即给您一个错误。

The code you listed for the for loop is a very common structure in C and the variable "i" should, indeed, be available inside the for loop body. Ie, the following should work:

您为for循环列出的代码是C中非常常见的结构,并且变量“i”应该在for循环体中可用。例如,以下方法应该有效:

int n = 0;
for (int i = 0; i < 10; i++) {
    n += i;
}

Am I misreading what you're saying?

我误解你的意思了吗?

#3


2  

The bottom line with respect to your for/fgets confusion is that while "enclosing braces control scope" is the correct rule in C most of the time, there is another rule regarding scope in C99 (borrowed from C++) that says that a variable declared in the prologue of a control structure (i.e. for, while, if) is in scope in the body of the structure (and is not in scope outside the body).

底线函数/困惑关于你的是,虽然“封闭括号控制范围”是正确的规则在C语言中大多数时候,C99中还有另一个规则关于范围(借用c++)说,序言中声明一个变量的控制结构(例如,如果是在范围的主体结构(并不是在身体以外的范围)。