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;
}
在案例1之后没有大括号:它给出了一个错误:*
标签只能是声明的一部分而声明不是a 声明:int val;
*
答案 0 :(得分:2)
这就是C语法的定义方式。变量声明不被视为语句:
int x; //a declaration
int y = 3; //another declaration
x = y + 1; //a statement
标签必须后跟声明。不允许使用标签和声明。
foo: int x; //error
bar: x = y +1; //ok
即IMO,不方便:
while (...)
{
//...
goto end;
end: //error, no statement
}
请记住,case
只是一种特殊的标签,所以:
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
作为脚注,由于现代C允许混合声明和语句,您还可以写:
case 1:; int x; //ok: label plus empty statement.
因为隔离的;
是一个空语句,所以只要需要一个无操作语句,它就可以用来满足语法。
是否使用;
或{ ... }
是可读性的问题。在end:
示例中,我使用;
,但在case:
我更喜欢{...}
。
while (...)
{
//...
goto end;
end:; //ok, empty statement
}
switch (...)
{
case 1: //ok, compound statement
{
int x;
}
}
当然可以编写更具创造性的解决方案,例如:
case 1: {} int x; //ok, label plus empty compound statement
答案 1 :(得分:2)
阻止声明遵循案例标签的C标准规则如下:
案例标签后面必须跟陈述(C 2011 [N1570] 6.8.1)。
C标准将语句定义为标记语句,复合语句,表达式语句之一, selection-statement , iteration-statement 或 jump-statement (6.8)。这些都不是声明。
C标准分别处理声明和声明。允许声明与语句混合的规则是 compound-statement 是大括号中 block-item 的列表(即 {< / strong> block-item-list opt } )(6.8.2)和块项目被定义为声明或声明。因此,在大括号内,您可以混合声明和语句。但案件标签必须是声明的一部分;它不是一个单独的东西,你可以插入任何地方。
声明可以使用两个备选方案包含在交换机内。一种是在案例标签后使用空语句,如:
case 123:
;
int foo;
…
另一种方法是在案例标签之后使用复合语句,如:
case 123:
{
int foo;
…
}
通常,后者是优选的,因为foo
的范围仅限于复合语句,因此不能在switch语句的另一部分中意外使用。
除了历史,我没有看到这个原因。最初,声明比现在更加严格。在函数内部,声明必须是大括号内的第一个语句。在任何声明之后你都不能发表声明。在现代C中已经放松了,但为什么对案例标签后面的内容仍有限制?
声明不能遵循现代C中的case标签,因为上面的空语句示例与语句具有相同的语义:
case 123:
int foo;
也就是说,编译器必须准备好在执行的同一点创建和初始化一个新对象。由于它必须为合法的示例代码执行此操作,因此它也可以为此版本执行此操作。
我也没有看到句法或语法障碍。在案例标签的不断表达之后的冒号是非常明显的。 (常量表达式可以在? :
运算符中包含冒号,但与:
无关的第一个?
将是案例标签的结尾。)一旦解析到达该冒号,当前的解析状态似乎很干净。我不明白为什么它不能在那里承认声明或声明,正如它准备在case
之前做的那样。
(如果某人可以在语法中发现一个问题,那就是允许一个案例标签后面跟一个声明,这会很有趣。)
答案 2 :(得分:0)
首先要说的是,您发布的错误是与import UIKit
import GooglePlacePicker
class ViewController: UIViewController {
// Add a pair of UILabels in Interface Builder, and connect the outlets to these variables.
@IBOutlet var nameLabel: UILabel!
@IBOutlet var addressLabel: UILabel!
// The code snippet below shows how to create and display a GMSPlacePickerViewController.
@IBAction func pickPlace(_ sender: UIButton) {
let config = GMSPlacePickerConfig(viewport: nil)
let placePicker = GMSPlacePickerViewController(config: config)
present(placePicker, animated: true, completion: nil)
}
// To receive the results from the place picker 'self' will need to conform to
// GMSPlacePickerViewControllerDelegate and implement this code.
func placePicker(_ viewController: GMSPlacePickerViewController, didPick place: GMSPlace) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("Place name \(place.name)")
print("Place address \(place.formattedAddress)")
print("Place attributions \(place.attributions)")
}
func placePickerDidCancel(_ viewController: GMSPlacePickerViewController) {
// Dismiss the place picker, as it cannot dismiss itself.
viewController.dismiss(animated: true, completion: nil)
print("No place selected")
}
}
标签语句格式相关的语法错误。它允许您只使用可执行语句,而不是声明。在声明之前放一个空的陈述,你就可以了。请尝试以下方法:
case
第一个变量#include <stdio.h>
int main()
{
switch(3) {
int x = 3; /* the initializer is ignored by the compiler
* you can include declarations here, but as
* this code is never executed, the initializer
* never takes place. */
case 3:; /* <=== look this semicolon to allow the next declaration */
int y = 5;
printf("x = %d, y = %d\n", x, y);
break;
}
}
将被正确声明,但初始化程序将不会被执行,因为所选的case语句是与case标签x
对应的case语句。 3
将打印
printf
(注意:这发生在我的机器上,因为变量x = 0, y = 5
未初始化,未定义行为 预期)
在C中,多年来已经实现了一些关于在块中使用声明的演变。
在古代C中,变量只能在块的开头(x
和{
之间的代码片段声明,但是这种方法已被抛出,因为新的可能性是声明变量无论何时需要它(即使在块开始后的一些可执行句子之后)但是}
语句只允许放置可执行语句,而不是声明,这就是编译器错误的原因。 / p>
如果你遵循古老的C方式,你只能在切换后打开case
大括号之后声明新的局部变量,如:
{
虽然违反直觉,但自旧的K&amp; R代码起有效。这种方法的问题在于变量从定义点到switch语句结束都是有效的,因此,它对所有案例部分都是全局的。
另一种方式,是你建议的形式,你通过打开花括号来声明一个新的块。这也适用于旧的K&amp; R代码,并且更容易控制定义的变量的范围。就个人而言,我更喜欢第二种方法。块是一个可执行语句,因此使用它作为交换机的带标签的case语句没有问题(声明发生在它内部)。
案例标签不分隔代码块,它们标记可执行语句,因此它们的语法特定于switch(something) {
int var1;
case BLA_BLA:
/* use var1 here */
语句语法(在附加到语句的分号后完成,或者关闭卷曲br)