1

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私は常に良い習慣で あるレッスンを学びます

4

3 に答える 3

3

したがって、コードに余分なセミコロンがないとコンパイルできないため、この点に到達するために実際に作業する必要があります。これは、インタビューなどのために作られた作為的な例だと思います。

2 番目の例では、変数 a (内部) がスイッチ中かっこ { } で作成されますが、初期化はケース 0: コードでのみ行われるため、そのレベルでは初期化されません。したがって、 a の値は完全にランダムです (たまたまゼロになります)

いずれにせよ、悪いコーディング スタイルです! 変数を導入する場合は、case ステートメントで中括弧を使用することを忘れないでください。[g ++では、実際には「大文字と小文字のラベルにジャンプすると、「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;
}

これは、2 番目のバリアントのコードと意味的に同じです。見た目がちょっと違うだけ!

于 2012-12-24T14:16:41.443 に答える
1

'{}' がないと、内部変数 'a' の初期化をジャンプするだけなので (まだ定義されています)、初期化されていない 'a' が得られます。この場合は '0' です。

ところで、'{}' を使用すると、'5' が出力されます。

于 2012-12-24T14:11:48.887 に答える