Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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
带大括号和不带大括号的switch语句_C_Assembly - Fatal编程技术网

带大括号和不带大括号的switch语句

带大括号和不带大括号的switch语句,c,assembly,C,Assembly,我只是写了一个简单的程序来学习c编程 1 #include<stdio.h> 2 3 int main() 4 { 5 int a = 5; 6 switch(a) 7 { 8 case 0: 9 { 10 ; 11 in

我只是写了一个简单的程序来学习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 }

输出:0

我对此有点困惑,并尝试编译和调试:


-1 0x000000000040051c:推送%rbp |-1 0x000000000040051c:推送%rbp
|2 0x0000000000040051D:mov%rsp%rbp | 2 0x0000000000040051D:mov%rsp%rbp
|3 0x00000000000400520:sub$0x10,%rsp | 3 0x00000000000400520:sub$0x10,%rsp
|4=>0x00000000000400524:movl$0x5,-0x8(%rbp)| 4=>0x00000000000400524:movl$0x5,-0x8(%rbp)
|5 0x0000000000040052B:mov-0x8(%rbp),%eax | | 5 0x0000000000040052B:mov-0x8(%rbp),%eax
|6 0x00000000004052E:测试%eax,%eax | | 6 0x00000000004052E:测试%eax,%eax
|7 0x00000000000400530:jne 0x40054f | 7 0x00000000000400530:jne 0x40054f
|8 0x00000000000400532:movl$0xa,-0x4(%rbp)| 8 0x00000000000400532:movl$0xa,-0x4(%rbp)
9 0x00000000000400539:mov-0x4(%rbp),%eax | 9 0x00000000000400539:mov-0x4(%rbp),%eax
10 0x0000000000040053C:mov%eax,%esi | 10 0x0000000000040053C:mov%eax,%esi
11 0x0000000000040053E:mov$0x400614%edi | 11 0x0000000000040053E:mov$0x400614%edi
12 0x00000000000400543:mov$0x0,%eax | 12 0x00000000000400543:mov$0x0,%eax
13 0x0000000000400548:callq 0x4003f0 | 13 0x0000000000400548:callq 0x4003f0
14 0x0000000000040054D:jmp 0x400563 | 14 0x0000000000040054D:jmp 0x400563
15 0x0000000000040054F:mov-0x8(%rbp),%eax | 15 0x0000000000040054F:mov-0x4(%rbp),%eax
16 0x00000000000400552:mov%eax,%esi | 16 0x00000000000400552:mov%eax,%esi
17 0x00000000000400554:mov$0x400618%edi | 17 0x00000000000400554:mov$0x400618%edi
18 0x0000000000400559:mov$0x0%eax | 18 0x0000000000400559:mov$0x0%eax
19 0x00000000004055E:callq 0x4003f0 | 19 0x00000000004055E:callq 0x4003f0
20 0x00000000000400563:mov$0x0%eax | 20 0x00000000000400563:mov$0x0%eax
21 0x0000000000400568:leaveq | 21 0x0000000000400568:leaveq
+22+--2行:0x0000000000400569:retq----------------------------22+--2行:0x0000000000400569:retq---------------------
有点不同,但很重要:

$ diff with.txt without.txt 
15c15
<    0x000000000040054f <+51>:  mov    -0x8(%rbp),%eax
---
>    0x000000000040054f <+51>:  mov    -0x4(%rbp),%eax
$diff with.txt with.txt with.txt
15c15
<0x000000000040054f:mov-0x8(%rbp),%eax
---
>0x000000000040054f:mov-0x4(%rbp),%eax
提前谢谢


更新:
我学到了一个教训,
gcc-Wall
始终是一个很好的实践

如果没有“{}”,您只需跳过内部变量“a”的初始化(尽管它仍然定义),因此您会得到一个未初始化的“a”,在本例中,它是“0”


顺便说一句,如果使用“{}”,它应该输出“5”。

如果不使用“{}”,您只需跳过内部变量“a”的初始化(尽管它仍然定义),因此您会得到一个未初始化的“a”,在本例中,它是“0”


顺便说一句,使用“{}”,它应该输出“5”。

因此您必须真正努力达到这一点,因为如果代码中没有额外的分号,它将无法编译。这让我觉得这是一个人为的例子,为采访或类似的事情而编造的

在第二个示例中,变量a(内部)是在开关括号{}处创建的,但它没有在该级别初始化,因为初始化仅在0:code的情况下进行。所以a的值是完全随机的(恰好为零)

不管怎样,糟糕的编码风格!如果引入变量,不要忘记在case语句中使用大括号。[在g++中,实际上会出现一个错误“跳转到大小写标签跨越'int a'的初始化]

因此,首先,
gcc-Wall
将对“未斜体化变量”发出警告

如果我们考虑这个例子:

int a = 111;

int main()
{
    int a = 2;

    printf("a=%d\n", a);
}
我不认为有人会争论“我们指的是哪一个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;
}

现在,这与第二个变体中的代码在语义上是一样的。它只是看起来有点不同!

因此,您必须真正努力达到这一点,因为如果代码中没有额外的分号,它将无法编译。这让我认为这是为采访或类似活动而设计的示例

在第二个示例中,变量a(内部)是在开关括号{}处创建的,但它没有在该级别初始化,因为初始化仅在0:code的情况下进行。因此a的值是完全随机的(恰好为零)

无论哪种方式,都是糟糕的编码风格!如果引入变量,不要忘记在case语句中使用大括号。[在g++中,您实际上会得到一个错误“跳转到case标签跨越'int a'的初始化]

因此,首先,
gcc-Wall
将对“未斜体化变量”发出警告

如果我们考虑这个例子:

int a = 111;

int main()
{
    int a = 2;

    printf("a=%d\n", a);
}
我不认为有人会争论“我们指的是哪一个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;
}

现在,这在语义上与第二个变体中的代码相同。只是看起来有点不一样

我很欣赏在帖子中使用assembly作为 它有助于
    .file   "test1.c"
    .section    .rodata
.LC0:
    .string "%d in case 0\n"
.LC1:
    .string "%d in default case\n"
    .text
.globl main
    .type   main, @function
main:
    pushl   %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $32, %esp
    movl    $5, 28(%esp)
    movl    28(%esp), %eax
    testl   %eax, %eax
    jne .L6
.L3:
    movl    $10, 24(%esp)
    movl    $.LC0, %eax
    movl    24(%esp), %edx
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    printf
    jmp .L4
.L6:
    movl    $.LC1, %eax
    movl    28(%esp), %edx
    movl    %edx, 4(%esp)
    movl    %eax, (%esp)
    call    printf
.L4:
    movl    $0, %eax
    leave
    ret
movl    $5, 28(%esp)
movl    28(%esp), %eax
testl   %eax, %eax its a switch equivalent
switch(a)
    {
    case 0:
        ;
        int a = 10;
        printf("%d in case 0\n",a);
        break;
    default:
        printf("%d in default case\n",a);
        break;
    }
switch(a)
    {
    case 5:
        ;
        int a = 10;
        printf("%d in case 5\n",a);
    default:
        printf("%d in default case\n",a);
        break;
    }
switch(a)
    {
    case 0:
        ;
        static int a = 10;
        printf("%d in case 0\n",a);
        break;
    default:
        printf("%d in default\n",a);
        break;
    }
switch(a)
    {
    case 0:
        {
        ;
        static int a = 10;
        printf("%d in case 0\n",a);
        break;
        }
    default:
        printf("%d in default\n",a);
        break;
    }