statement - ¿Por qué no encender los punteros?
switch case c# (11)
Por ejemplo:
#include <stdio.h>
void why_cant_we_switch_him(void *ptr)
{
switch (ptr) {
case NULL:
printf("NULL!/n");
break;
default:
printf("%p!/n", ptr);
break;
}
}
int main(void)
{
void *foo = "toast";
why_cant_we_switch_him(foo);
return 0;
}
gcc test.c -o test
test.c: In function ''why_cant_we_switch_him'':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values
Sólo curioso. ¿Es esto una limitación técnica?
EDITAR
La gente parece pensar que solo hay una expresión de puntero constante. Sin embargo, ¿es eso realmente cierto? Por ejemplo, aquí hay un paradigma común en Objective-C (en realidad es solo C aparte de NSString
, id
y nil
, que son meramente un puntero, por lo que sigue siendo relevante; solo quería señalar que, de hecho, , un uso común para él, a pesar de que es solo una cuestión técnica):
#include <stdio.h>
#include <Foundation/Foundation.h>
static NSString * const kMyConstantObject = @"Foo";
void why_cant_we_switch_him(id ptr)
{
switch (ptr) {
case kMyConstantObject: // (Note that we are comparing pointers, not string values.)
printf("We found him!/n");
break;
case nil:
printf("He appears to be nil (or NULL, whichever you prefer)./n");
break;
default:
printf("%p!/n", ptr);
break;
}
}
int main(void)
{
NSString *foo = @"toast";
why_cant_we_switch_him(foo);
foo = kMyConstantObject;
why_cant_we_switch_him(foo);
return 0;
}
gcc test.c -o test -framework Foundation
test.c: In function ''why_cant_we_switch_him'':
test.c:5: error: switch quantity not an integer
test.c:6: error: pointers are not permitted as case values
Parece que la razón es que el cambio solo permite valores integrales (como decía la advertencia del compilador). Entonces, supongo que una mejor pregunta sería preguntar por qué este es el caso. (Aunque es probable que sea demasiado tarde ahora).
Porque solo hay una expresión de puntero constante
Dado que solo existe una única expresión de puntero constante, la instrucción switch
tiene poco que ofrecer expresiones de puntero. Usted ha citado esencialmente la única construcción posible.
Doh! ¿Por qué usar una declaración de cambio? las declaraciones de cambio solo se deben usar si tiene 3 o más opciones para elegir si tiene 2 opciones y luego usa una declaración if () {} else {}.
joshua esto no es un uso legítimo de un puntero en un interruptor.
Si realmente debe usar una sentencia switch, entonces colóquela en un _int64 o long long o en algún tipo integral que garantice que sea tan grande o más grande que un puntero (depende del compilador).
Además, algunos compiladores pueden limitar el tamaño máximo de un interruptor a un int u otro tamaño arbitrario. en este caso, no puede usar una declaración de cambio en absoluto.
corriente continua
Los enunciados de cambio operan solamente en valores integrales. Es por eso que el mensaje de error es "cambiar cantidad no un número entero". No creo que sea una limitación técnica sino fuera de la sintaxis del lenguaje.
Puede estar relacionado con la forma en que se implementa el cambio: parece esperar como mucho un número entero, por lo que puede usar un determinado registro de CPU que podría no ser posible con un puntero.
Puedes (si realmente debes). Simplemente eche el puntero a un entero de tamaño apropiado . Para este intptr_t
debe ser utilizado. Eso no quiere decir que lo recomendaría, pero puede que tenga sus razones.
#include <stdint.h>
#include <stdio.h>
void we_can_switch_him(void *ptr)
{
switch ((intptr_t)ptr) {
case (intptr_t)NULL:
printf("NULL!/n");
break;
default:
printf("%p!/n", ptr);
break;
}
}
int main(void)
{
void *foo = "toast";
we_can_switch_him(foo);
return 0;
}
Solo necesita este cambio en su interruptor: [ptr intvlue]
void why_cant_we_switch_him(void *ptr)
{
switch ([ptr intvalue]) {
case NULL:
printf("NULL!/n");
break;
default:
printf("%p!/n", ptr);
break;
}
}
Transmite ptr a int y vuelve a intentarlo:
switch( (int)ptr )
o para ser más correcto:
switch( (intptr_t)ptr ) // C99 integer type to hold a pointer
Un conmutador compara la variable con un conjunto de constantes de tiempo de compilación . Aparte de nulo, no puedo ver ninguna constante de tiempo de compilación válida con la que pueda comparar un puntero. Por ejemplo:
switch (ptr) {
case &var1: printf ("Pointing to var1"); break;
case &var2: printf ("Pointing to var2"); break;
}
var1 y var2 son probablemente diferentes en cada ejecución del programa, y no serían constantes de tiempo de compilación. Una posibilidad podría ser que sean direcciones de puertos mapeados en memoria que siempre son fijos, pero de lo contrario no veo cómo podría expandir esto fácilmente desde sus dos casos (null / not-null).
case
etiquetas de los case
esperan una expresión constante, generalmente un número entero, y los indicadores tienden a no ser bien comparados con estos, excepto en el caso de NULL. Puedes lanzar a intptr_t, pero sigue sin sentido cuando solo tienes una cosa con la que puedes comparar.
switch
instrucciones de switch
existen porque el compilador a menudo puede convertirlas en una tabla de salto , que es un concepto que funciona mejor si las etiquetas de su caso son enteros consecutivos. Pero en el caso de un puntero fundido al tipo integral, no se gana nada en un if
/ else
usando el interruptor, excepto una sintaxis más engorrosa.
switch
sentencias switch
operan en expresiones integrales. Un puntero no es una expresión integral.
Puede convertir explícitamente un puntero a un tipo integral si lo desea, pero el código propuesto es un poco extraño y antinatural.
Entonces, para responder exactamente a su pregunta: porque no hay conversión implícita entre un puntero y un tipo integral.
enum boolean
{
FALSE=0,
TRUE=!FALSE
}boolean;
...
void *ptr=NULL;
...
switch((!ptr))
{
case FALSE:
...
break;
case TRUE:
...;
break;
}
...
Es posible encender el puntero.