我只是写一个简单的程序来学习c编程
1 #include<stdio.h>
2
3 int main()
4 {
5 int a = 5;
6 switch(a)
7 {
8 case 0:
9 {
10 ;
11 int a = 10;
12 printf("%d\n",a);
13 break;
14 }
15 default :
16 printf("%d",a);
17
18 }
19 return 0;
20 }
输出:5
当我忘了撑杆的时候,它变成了:
8 case 0:
9
10 ;
11 int a = 10;
12 printf("%d\n",a);
13 break;
14
输出:0
我对此有点困惑,并尝试编译和调试:
- 1 0x000000000040051c <+0>: push %rbp |- 1 0x000000000040051c <+0>: push %rbp
| 2 0x000000000040051d <+1>: mov %rsp,%rbp || 2 0x000000000040051d <+1>: mov %rsp,%rbp
| 3 0x0000000000400520 <+4>: sub $0x10,%rsp || 3 0x0000000000400520 <+4>: sub $0x10,%rsp
| 4 => 0x0000000000400524 <+8>: movl $0x5,-0x8(%rbp) || 4 => 0x0000000000400524 <+8>: movl $0x5,-0x8(%rbp)
| 5 0x000000000040052b <+15>: mov -0x8(%rbp),%eax || 5 0x000000000040052b <+15>: mov -0x8(%rbp),%eax
| 6 0x000000000040052e <+18>: test %eax,%eax || 6 0x000000000040052e <+18>: test %eax,%eax
| 7 0x0000000000400530 <+20>: jne 0x40054f <main+51> || 7 0x0000000000400530 <+20>: jne 0x40054f <main+51>
| 8 0x0000000000400532 <+22>: movl $0xa,-0x4(%rbp) || 8 0x0000000000400532 <+22>: movl $0xa,-0x4(%rbp)
9 0x0000000000400539 <+29>: mov -0x4(%rbp),%eax | 9 0x0000000000400539 <+29>: mov -0x4(%rbp),%eax
10 0x000000000040053c <+32>: mov %eax,%esi | 10 0x000000000040053c <+32>: mov %eax,%esi
11 0x000000000040053e <+34>: mov $0x400614,%edi | 11 0x000000000040053e <+34>: mov $0x400614,%edi
12 0x0000000000400543 <+39>: mov $0x0,%eax | 12 0x0000000000400543 <+39>: mov $0x0,%eax
13 0x0000000000400548 <+44>: callq 0x4003f0 <printf@plt> | 13 0x0000000000400548 <+44>: callq 0x4003f0 <printf@plt>
14 0x000000000040054d <+49>: jmp 0x400563 <main+71> | 14 0x000000000040054d <+49>: jmp 0x400563 <main+71>
15 0x000000000040054f <+51>: mov -0x8(%rbp),%eax | 15 0x000000000040054f <+51>: mov -0x4(%rbp),%eax
16 0x0000000000400552 <+54>: mov %eax,%esi | 16 0x0000000000400552 <+54>: mov %eax,%esi
17 0x0000000000400554 <+56>: mov $0x400618,%edi | 17 0x0000000000400554 <+56>: mov $0x400618,%edi
18 0x0000000000400559 <+61>: mov $0x0,%eax | 18 0x0000000000400559 <+61>: mov $0x0,%eax
19 0x000000000040055e <+66>: callq 0x4003f0 <printf@plt> | 19 0x000000000040055e <+66>: callq 0x4003f0 <printf@plt>
20 0x0000000000400563 <+71>: mov $0x0,%eax | 20 0x0000000000400563 <+71>: mov $0x0,%eax
21 0x0000000000400568 <+76>: leaveq | 21 0x0000000000400568 <+76>: leaveq
+ 22 +-- 2 lines: 0x0000000000400569 <+77>: retq ----------------------|+ 22 +-- 2 lines: 0x0000000000400569 <+77>: retq ---------------------
有点不同但很重要:
$ diff with.txt without.txt
15c15
< 0x000000000040054f <+51>: mov -0x8(%rbp),%eax
---
> 0x000000000040054f <+51>: mov -0x4(%rbp),%eax
提前谢谢。
更新:
我学到了一个教训,那就是
gcc -Wall
总是一个很好的做法 最佳答案
因此,您必须真正做到这一点,因为如果代码中没有额外的分号,它将无法编译。这让我觉得这是一个人为的例子,是为一次面试或其他类似的事情做的。
在第二个示例中,变量a(内部)是在开关大括号{}处创建的,但它没有在该级别进行初始化,因为初始化仅在case 0:code中进行。所以a的值是完全随机的(碰巧是零)
不管怎样,糟糕的编码风格!如果引入变量,不要忘记在case语句中使用大括号。[在g++中,您实际上得到一个错误“跳转到case label crosss initialization of‘int a’]
因此,首先,gcc -Wall
将对“未斜体变量”发出警告。
如果我们考虑这个例子:
int a = 111;
int main()
{
int a = 2;
printf("a=%d\n", a);
}
我不认为有人会争论“我们指的是哪一个”,对吧?
或者如果我们有:
int main()
{
int x = 12;
int a = 11;
if(x == 12)
{
int a = 2;
printf("a=%d\n", a);
}
}
同样,很明显这里发生了什么,对吧?
如果我们重写代码以显示实际发生的情况:
int main()
{
int a = 5;
switch(a)
{
int a;
case 0:
a=10 ;
printf("%d\n",a);
break;
default :
printf("%d",a);
}
return 0;
}
现在,这和第二个变量中的代码在语义上是一样的。只是看起来有点不一样!