paulo1205
(usa Ubuntu)
Enviado em 11/03/2019 - 03:42h
Isso é parte da linguagem, mesmo.
O comando
switch () não é uma maneira mais bonita de reescrever uma tripa de
if /
else if /
else if /.../
else . O valor passado ao
switch () tem de ser um valor inteiro e produzido por uma expressão, e provoca um desvio da execução para o valor passado como rótulo de algum
case (ou do caso
default ), de modo semelhante ao funcionamento de
goto , podendo usar uma tabela de possíveis locais de desvio, em lugar de testar cada valor sequencialmente até encontrar o valor correto, como ocorreria com a tripa de
if /
else if /
else if /.../
else .
Um paralelo dele em outras linguagem seria, no BASIC, o comando
ON expressão GOTO endereço0 , endereço1 [, ...], endereçoN , em que o fluxo de execução desviaria para
endereço0 se
expressão valesse
0 , para
endereço1 se ela valesse
1 , e assim por diante, até
endereçoN se ela valesse
N .
Para você ter uma ideia, o seguinte programa em C padrão produz um código executável muito semelhante ao segundo programa seguinte (que usa extensões do GCC para obtenção do endereço de
labels e para usar um valor não-constante para
goto ).
int main(int argc, char **argv){
switch(argc){
default:
return -1;
case 10:
return 1;
case 20:
return 2;
case 30:
return 3;
case 40:
case 50:
return 4;
case 60:
return 6;
}
}
/* Usa extensões do GCC -- não é C padrão. */
int main(int argc, char **argv){
static void *const labels[51]={
&&lb10, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf,
&&lb20, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf,
&&lb30, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf,
&&lb40, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf,
&&lb50, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf, &&lbdf,
&&lb60
};
if(argc>=10 && argc<=60)
goto *labels[argc-10];
lbdf:
return -1;
lb10:
return 1;
lb20:
return 2;
lb30:
return 3;
lb40:
;
lb50:
return 4;
lb60:
return 6;
}
Em outras linguagens, pode ser que elementos relativamente parecidos com o
switch () do C, como o
SELECT CASE do Visual Basic, não possam ser implementados dessa maneira, mas tenham de recorrer ao funcionalmente equivalente à tripa de
if /
else if /
else if /.../
else , especialmente quando o tipo que está sendo avaliado for algo complexo, como
strings , ou quando os próprios valores das expressões de cada caso distinto não forem constantes. Por exemplo, o seguinte código em Visual Basic não tem como ter correspondente visual direto em C.
Dim Str1, Str2 as String
' ...
Select Case Str1
Case "Paulo", "Nick"
Debug.WriteLine("Usuário do VoL.")
Case Str2
Debug.WriteLine("Sei quem é "+Str2+", mas não sei se usa o VoL.")
Case Else
Debug.WriteLine("Não conheço nenhum "+Str1+".")
End Select
A conversão do código acima para C teria de usar uma tripa de
if s explícita.
char *str1, *str2;
/* ... */
if(strcmp(str1, "Paulo")==0 || strcmp(str1, "Nick")==0)
puts("Usuário do VoL.");
else if(strcmp(str1, str2)==0)
printf("Sei quem é %s, mas não sei se usa o VoL.\n", str2);
else
printf("Não conheço nenhum %s.\n", str1);
Note, aliás, que o próprio fato de não haver um tipo nativo para
strings em C dificulta a criação de algo como uma versão de
switch que saiba manipular tais dados.
Por fim, vale ressaltar que é possível que o compilador C, em algumas situações, produza código equivalente às tripas de
if s. Seria muito caro, por exemplo, gerar um
array de ponteiros com milhares ou milhões de índices para uma construção tão simples como a seguinte.
switch(valor){
case -100000000: puts("Muito negativo."); break;
case 100000000: puts("Muito positivo."); break;
case 0: puts("Zero."); break;
default: puts("Sei lá!");
}
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)