Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么我们不能在不使用大括号的情况下在开关大小写冒号后声明变量?_C - Fatal编程技术网

C 为什么我们不能在不使用大括号的情况下在开关大小写冒号后声明变量?

C 为什么我们不能在不使用大括号的情况下在开关大小写冒号后声明变量?,c,C,在案例1之后没有大括号:它给出了一个错误:* 标签只能是语句的一部分,而声明不是 声明:int val *这就是C语法的定义。变量声明不被视为语句: case 1: { //question is about this curly brace int val; scanf("%d", &val); if(top1 == NULL){

在案例1之后没有大括号:它给出了一个错误:*

标签只能是语句的一部分,而声明不是 声明:int val


*这就是C语法的定义。变量声明不被视为语句:

case 1:
            { //question is about this curly brace
                int val;
                scanf("%d", &val);
                if(top1 == NULL){
                    enqueue(top1, val, bottom1);
                }
                else{
                    enqueue(top1, val);
                }
                break;
            }
标签后面必须有一个声明。不允许标签加声明

int x; //a declaration
int y = 3; //another declaration
x = y + 1; //a statement
也就是说,IMO不方便:

foo: int x; //error
bar: x = y +1; //ok
请记住,箱子只是一种特殊的标签,因此:

while (...)
{
    //...
    goto end;
    end:   //error, no statement   
}
大括号的问题是,在C语言中,大括号用于构建复合语句,这当然是一种语句。复合语句中的行可以是声明和语句,所有混合的旧C版本只允许在开始时声明,而不是在中间。因此:

case 1: int x; //error
case 2: x = y +1; //ok
作为脚注,由于现代C允许混合声明和语句,您还可以编写:

case 1: int x; //error: label plus declaration
case 2: { int x; } //ok: label plus compound statement
因为是孤立的,;是一个空语句,它可以用于满足任何需要no op语句的语法

是否使用;或者{…}是可读性的问题。最后:我将使用一个;,但在这种情况下:我更喜欢{…}

当然,可以编写更具创造性的解决方案,例如:

while (...)
{
    //...
    goto end;
    end:;   //ok, empty statement   
}

switch (...)
{
    case 1: //ok, compound statement
    {
        int x;
    }
}

这就是C语法的定义。变量声明不被视为语句:

case 1:
            { //question is about this curly brace
                int val;
                scanf("%d", &val);
                if(top1 == NULL){
                    enqueue(top1, val, bottom1);
                }
                else{
                    enqueue(top1, val);
                }
                break;
            }
标签后面必须有一个声明。不允许标签加声明

int x; //a declaration
int y = 3; //another declaration
x = y + 1; //a statement
也就是说,IMO不方便:

foo: int x; //error
bar: x = y +1; //ok
请记住,箱子只是一种特殊的标签,因此:

while (...)
{
    //...
    goto end;
    end:   //error, no statement   
}
大括号的问题是,在C语言中,大括号用于构建复合语句,这当然是一种语句。复合语句中的行可以是声明和语句,所有混合的旧C版本只允许在开始时声明,而不是在中间。因此:

case 1: int x; //error
case 2: x = y +1; //ok
作为脚注,由于现代C允许混合声明和语句,您还可以编写:

case 1: int x; //error: label plus declaration
case 2: { int x; } //ok: label plus compound statement
因为是孤立的,;是一个空语句,它可以用于满足任何需要no op语句的语法

是否使用;或者{…}是可读性的问题。最后:我将使用一个;,但在这种情况下:我更喜欢{…}

当然,可以编写更具创造性的解决方案,例如:

while (...)
{
    //...
    goto end;
    end:;   //ok, empty statement   
}

switch (...)
{
    case 1: //ok, compound statement
    {
        int x;
    }
}
C关于案例标签的规则 C标准中防止声明遵循案例标签的规则如下:

箱子标签后面必须附有C 2011[N1570]6.8.1的声明

C标准将语句定义为标记语句、复合语句、表达式语句、选择语句、迭代语句或跳转语句6.8中的一种。这些都不是宣言

C标准将声明和语句分开处理。允许声明在很大程度上与语句混合的规则是,复合语句是大括号中的块项列表,即{block item listopt}6.8.2,块项定义为声明或语句。因此,在大括号内,可以混合声明和语句。但案例标签必须是声明的一部分;它不是一个单独的东西,你可以在任何地方插入

可以使用两种替代方法将声明包含在交换机中。一种是在案例标签后使用空语句,如:

case 1: {} int x; //ok, label plus empty compound statement
case 123:
    ;
    int foo;
    …
另一种方法是在案例标签后使用复合语句,如中所示:

case 1: {} int x; //ok, label plus empty compound statement
case 123:
    ;
    int foo;
    …
一般来说,后者更可取,因为foo的作用域仅限于复合语句,因此不能在switch语句的另一部分中意外使用它

制定规则的理由 除了历史之外,我看不到其他原因。最初,声明比现在更受限制。在函数中,声明必须是大括号中的第一个语句。您不能在任何声明之后添加声明。这在现代C语言中已经被放宽了,但是为什么在case标签后面还有一个限制呢

在现代C语言中,声明不能跟在case标签后面并没有语义上的原因,因为上面的空语句示例的语义与:

case 123:
{
    int foo;
    …
}
也就是说,编译器必须准备在同一执行点创建和初始化新对象。因为它必须为法律示例代码这样做,所以它也可以为这个版本这样做

我也没有看到语法或句法上的障碍。大小写标签的常量表达式后面的冒号非常明显。常量表达式中可以有冒号,从?:运算符,但第一个:不与关联?将是案例标签的结尾。一旦解析到达该冒号,当前的解析状态看起来是干净的。我不明白为什么它不能承认那里有一项声明或一项声明,就像它在案发前准备做的那样

如果有人能在语法中发现一个问题,而这个问题是由允许一个case标签后面跟一个声明引起的,那么 t会很有趣。

C关于案例标签的规则 C标准中防止声明遵循案例标签的规则如下:

箱子标签后面必须附有C 2011[N1570]6.8.1的声明

C标准将语句定义为标记语句、复合语句、表达式语句、选择语句、迭代语句或跳转语句6.8中的一种。这些都不是宣言

C标准将声明和语句分开处理。允许声明在很大程度上与语句混合的规则是,复合语句是大括号中的块项列表,即{block item listopt}6.8.2,块项定义为声明或语句。因此,在大括号内,可以混合声明和语句。但案例标签必须是声明的一部分;它不是一个单独的东西,你可以在任何地方插入

可以使用两种替代方法将声明包含在交换机中。一种是在案例标签后使用空语句,如:

case 1: {} int x; //ok, label plus empty compound statement
case 123:
    ;
    int foo;
    …
另一种方法是在案例标签后使用复合语句,如中所示:

case 1: {} int x; //ok, label plus empty compound statement
case 123:
    ;
    int foo;
    …
一般来说,后者更可取,因为foo的作用域仅限于复合语句,因此不能在switch语句的另一部分中意外使用它

制定规则的理由 除了历史之外,我看不到其他原因。最初,声明比现在更受限制。在函数中,声明必须是大括号中的第一个语句。您不能在任何声明之后添加声明。这在现代C语言中已经被放宽了,但是为什么在case标签后面还有一个限制呢

在现代C语言中,声明不能跟在case标签后面并没有语义上的原因,因为上面的空语句示例的语义与:

case 123:
{
    int foo;
    …
}
也就是说,编译器必须准备在同一执行点创建和初始化新对象。因为它必须为法律示例代码这样做,所以它也可以为这个版本这样做

我也没有看到语法或句法上的障碍。大小写标签的常量表达式后面的冒号非常明显。常量表达式中可以有冒号,从?:运算符,但第一个:不与关联?将是案例标签的结尾。一旦解析到达该冒号,当前的解析状态看起来是干净的。我不明白为什么它不能承认那里有一项声明或一项声明,就像它在案发前准备做的那样


如果有人能在语法中发现一个问题,而这个问题是由于允许一个case-label后面跟一个声明引起的,那将是一个有趣的问题。

首先,您发布的错误是一个与case-label语句的格式相关的语法错误。它只允许使用可执行语句,而不允许使用声明。在声明前放一个空语句,你就可以了。请尝试以下操作:

case 123:
    int foo;
注意:这种情况发生在我的机器上,因为变量x未初始化,所以预期会出现未定义的行为

在C语言中,关于在块中使用声明,多年来已经实现了一些改进

在古代的C语言中,变量只能在块的开始处声明,{和}之间的代码段,但是这种方法已经被提出,因为在块开始后,即使在一些可执行语句之后,只要你需要,也可以在任何时候声明变量,但是case语句只允许放置一个可执行语句,而不是声明,所以这就是编译器错误的原因

如果遵循古老的C方式,则只能在开关后打开{大括号后声明新的局部变量,如:

x = 0, y = 5
这种方法的问题在于,变量从定义到switch语句结束都是有效的,因此,它对所有case部分都是全局的

另一种方法是您提出的形式,在这种形式中,您可以通过打开大括号来声明一个新块。这也适用于旧的K&R代码,并使其更易于控制定义的变量范围。就个人而言,我更喜欢第二种方法。块是一个可执行语句,因此使用它作为标记的case stateme没有问题声明发生在开关的内部


大小写标签不划分代码块,它们标记可执行语句,因此它们的语法特定于大小写语句语法,该语法在它所附加的语句分号或结尾卷曲后结束br

首先,您发布的错误是与大小写标签语句格式相关的语法错误。它允许您必须仅使用可执行语句,而不是声明。请在声明之前放置一个空语句,这样您就可以了。请尝试以下操作:

case 123:
    int foo;
注意:这发生在我的机器上,因为变量x未初始化,未定义行为 我们希望

在C语言中,关于在块中使用声明,多年来已经实现了一些改进

在古代的C语言中,变量只能在块的开始处声明,{和}之间的代码段,但是这种方法已经被提出,因为在块开始后,即使在一些可执行语句之后,只要你需要,也可以在任何时候声明变量,但是case语句只允许放置一个可执行语句,而不是声明,所以这就是编译器错误的原因

如果遵循古老的C方式,则只能在开关后打开{大括号后声明新的局部变量,如:

x = 0, y = 5
这种方法的问题在于,变量从定义到switch语句结束都是有效的,因此,它对所有case部分都是全局的

另一种方法是您提出的形式,在这种形式中,您可以通过打开大括号来声明一个新块。这也适用于旧的K&R代码,并使其更易于控制定义的变量范围。就个人而言,我更喜欢第二种方法。块是一个可执行语句,因此使用它作为标记的case stateme没有问题声明发生在开关的内部


Case标签不划分代码块,它们标记可执行语句,因此它们的语法特定于Case语句语法,该语法在附加到语句的分号后结束,或者结束时的卷曲br

答案在错误itelf中。声明中不清楚的不是语句?是的,它是。它的正式名称是d是一个大小写标签。@RohitHegde:语法是这样说的。因为C标准区分了它们。故事结束。答案就在错误本身。声明中不清楚的不是一个语句?是的,它是。它被正式称为大小写标签。@RohitHegde:语法是这样说的。因为C标准区分了它们。故事结束。你可以使用continue;而不是goto end;,所以不是这样inconvenient@rodrigo:是否使用;或{…}不仅仅是可读性。在前者中,声明的标识符的范围扩展到switch语句的末尾。这意味着标识符可以在switch语句的后续部分中使用。如果switch语句结构良好,则一个部分中的标识符不会在其他部分中使用,我们更喜欢{declaration;…}为了避免事故。如果switch语句要求将案例传递给其他人,则该特定用途可能需要;;declaration;..。@EricPostDischil:关于传递,您可以编写案例1:{declaration;stmt1;案例2:stmt2;}但是我同意可读性会受到影响,最好在完全切换之前声明变量。您可以使用continue;而不是goto end;,所以不是这样inconvenient@rodrigo:是否使用;或{…}不仅仅是可读性。在前者中,声明的标识符的范围扩展到switch语句的末尾。这意味着标识符可以在switch语句的后续部分中使用。如果switch语句结构良好,则一个部分中的标识符不会在其他部分中使用,我们更喜欢{declaration;…}为了避免事故。如果switch语句要求将案例传递给其他人,则该特定用途可能需要;;declaration;..。@EricPostDischil:关于传递,您可以编写案例1:{declaration;stmt1;案例2:stmt2;}但我同意可读性会受到影响,最好在完全切换之前声明变量。