2010-01-20 4 views
15

В C можно написать код до первого case. Есть ли случаи, для которых это полезно, или это просто «мертвый блок кода»?Код перед первым «случаем» в операторе switch

т.д .:

switch (...) { 
    { 
    int a = 0x2a; 
    printf("%d\n", a); 
    } 
    case 0: 
    ... 
} 
+7

попробуйте его и посмотрите ??????????? –

+0

Я пробовал много разных примеров, и один из них просто разъясняет. Но всегда есть шанс, что я пропустил функцию (GNU) C, и что-то можно сделать в этом регионе. – tur1ng

ответ

11

Может быть полезно объявить переменные, которые имеют область действия, ограниченную блоком switch (но имейте в виду, что любые инициализаторы для этих переменных будет пропущено):

switch (...) 
{ 
    int n; 

    case 0: 
    ... 
} 

в теории, можно также поместить код там, что вы получите с помощью goto.

+0

Если вы хотите переменную в этой области, запустите блок непосредственно перед коммутатором и объявите здесь переменную, т. е. заключите весь оператор switch в другой набор скобок. Объявление его внутри коммутатора, но не в случае, не работает. – Martin

+2

@Martin: объявления переменных * do * работают, поскольку они не выдают никакого выходного кода; они просто для компилятора, чтобы отметить «Ах, я знаю эту переменную, я видел ее там». – Joey

+0

«любые инициализаторы для этих переменных могут быть пропущены» - это даже так просто (инициализатор либо пропущен, либо нет), либо это неопределенное поведение/некорректная программа для перехода через инициализатор? Я не помню. –

18

Я думаю, что это меньше, чем особенность артефакта как C лечит switch/case -как только ряд целей прыжковых без ограничений по синтаксису. Вот почему работает Duff's device, и поэтому код до первого case никогда не будет работать.

Если посмотреть на сгенерированный сборки, вы увидите, что код будет просто перепрыгнул:

mov ecx, DWORD PTR _x$[ebp] 
    mov DWORD PTR tv64[ebp], ecx 
    cmp DWORD PTR tv64[ebp], 0     ; here begins the switch 
    je SHORT [email protected]       ; jump to case 0 
    jmp SHORT [email protected]       ; jump out of the switch 
; Line 8 
    mov DWORD PTR _a$752[ebp], 42 
; Line 9 
    mov edx, DWORD PTR _a$752[ebp]    ; here we have the dead code 
    push edx 
    push OFFSET $SG754 
    call _printf 
    add esp, 8 
[email protected]:          ; and here case 0 
; Line 12 
    push OFFSET $SG756 
    call _printf 
    add esp, 4 
[email protected]: 
; Line 15 
    xor eax, eax 
    mov esp, ebp 
    pop ebp 
    ret 0 
1

Я не понимаю, что ваш после. Почему бы просто не поставить код перед делом?

int a = 0x2a; 
printf("%d\n", a); 
switch (...) { 
case 0: 
... 
} 

Разве это не то же самое, что вы намерены? (кроме вашего примера, код никогда не будет работать, если компилятор не будет жаловаться.)

+0

Печать в моем примере выбрана случайным образом. – tur1ng

+5

это имеет значение? вопросы должны быть заданы обо всем –

12

Стандартный документ С имеет пример, который точно объясняет поведение этого типа конструкции (6.8.4.2/7 «Переключатель заявление»):

Пример В фрагменте программы Arti фи CIAL

switch (expr) 
{ 
    int i = 4; 
    f(i); 
case 0: 
    i = 17; 
    /* falls through into default code */ 
default: 
    printf("%d\n", i); 
} 

объект с идентификатором i существует с автоматической продолжительностью хранения (внутри блока), но никогда не инициализируется, и, таким образом, если управляющее выражение имеет ненулевое значение, вызов функции printf будет иметь доступ к неопределенному значению. Аналогично, вызов функции f невозможен.

Так что, даже если это разрешено, легко один из таких ситуаций «только потому, что вы можете не означать, что вам». Конструкция запутанна и может легко привести к использованию неинициализированной переменной, поскольку может быть очень неясно, происходит ли и где происходит инициализация.

+1

C стандартный документ можно найти по адресу: http://www.open-std.org/JTC1/SC22/wg14/www/docs/n1336.pdf – tur1ng

Смежные вопросы