2009-08-05 3 views
102

Я увидел несколько ответов на эту проблему, и я понял - вы не можете объявлять и присваивать переменные внутри switch. Но мне интересно, если следующий правильно на метания ошибку говоряОбъявление переменных внутри оператора switch

error: expected expression before 'int'

Код:

switch (i) { 
    case 0: 
     int j = 1; 
     break; 
} 

Почему бы поставить вызов NSLog() прежде, чем это приведет к без ошибок?

switch (i) { 
    case 0: 
     NSLog(@"wtf"); 
     int j = 1; 
     break; 
} 
+1

Это было предложено (по крайней мере) дважды: http://stackoverflow.com/questions/92396/why-cant-variables-be-declared-in-a-switch-statement HTTP: // stackoverflow.com/questions/1115304/can-i-declare-variables-inside-an-objective-c-switch-statement –

+2

Верно, но оба эти вопроса по-прежнему открыты. Я не вижу проблемы с тем, чтобы позволить этому одному - не нужно голосовать, чтобы закрыть его ... –

+1

Адам, в то время как другое сообщение отвечает на ошибку, оно не касалось факта, что выражение в качестве первого вызова на самом деле избежать ошибки. Что-то Куинн ответил здесь. – dizy

ответ

132

Вы на самом деле может объявлять переменные внутри переключателя, если вы делаете это в соответствии с синтаксисом языка. Вы получаете сообщение об ошибке, потому что «case 0:» является ярлыком, а в C незаконно иметь объявление как первый оператор после метки - обратите внимание, что компилятор ожидает выражение, такое как вызов метода, обычный присваивание и т. д. (возможно, это может быть странно, но это правило.)

Когда вы ставите NSLog(), вы избегаете этого ограничения. Вы можете заключить содержимое фрейма в фигурные скобки {}, чтобы ввести блок видимости, или вы можете переместить объявление переменной за пределы коммутатора. Вы выбираете вопрос личного предпочтения. Просто имейте в виду, что переменная, объявленная в {} скобках, действительна только в пределах этой области, поэтому любой другой код, который ее использует, должен также отображаться в этих скобках.


Edit:

Кстати, эта особенность не так редко, как вы могли бы подумать. В C и Java, это также запрещено использовать локальные переменные декларации в качестве одинокого заявления (что означает «не в фигурных скобках) в для, то время как или сделать петли, или даже в случае и else. (На самом деле это рассматривается в головоломке № 55 от "Java Puzzlers", которую я очень рекомендую.) Я думаю, что мы вообще не пишем таких ошибок, потому что не имеет смысла объявлять переменную как единственное утверждение в таких ситуациях. С переключатель/корпус конструкции, однако, некоторые люди опускают скобки, так как перерывИнструкцияявляется критическим заявлением для потока управления.

Чтобы увидеть компилятор бросать припадки, скопировать этот ужасающий, бессмысленный фрагмент кода в ваш (код) объективно-C:

if (1) 
    int i; 
else 
    int i; 
for (int answer = 1; answer <= 42; answer ++) 
    int i; 
while (1) 
    int i; 
do 
    int i; 
while (1); 

Еще одна причина, чтобы всегда использовать {} скобки, чтобы разграничить тело таких конструкций. :-)

+0

Вау, это странно ... но спасибо! – dizy

+9

В общем случае, если переменная используется только в одном случае, то включение раздела case в {} будет лучше (оно позволяет избежать его повторного использования позже). Если переменная используется повторно, то имеет смысл объявить ее перед началом оператора switch, так как ее очень тупо в противном случае. –

+0

Я полностью согласен, используя вложенный объем с фигурными скобками, делает цель кристально чистой и может предотвратить случайные ошибки. Спасибо за разъяснения! –

39

Я столкнулся с этой проблемой раньше, и было заключено, что вы просто помещаете код внутри блока.

switch (i) { 
case 0: 
    { 
     int j = 1; 
     break; 
    } 
} 
4

Другим простым обходным решением, которое я использую, является добавление пустого выражения (точки с запятой) перед объявлением. Это позволяет ограничить область переменной блоком кода (или иметь некоторые операторы case с блоками кода, а некоторые - без).

switch (i) { 
    case 0:; 
     int j = 1; 
     break; 
} 
+0

Это дает мне ошибку в моем случае 'default':' Корпус переключателя находится в защищенной области. ' – zakdances

+0

@joel Nice hack :) – FreelanceAr

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