Puntero a valor literal

Supongamos que tengo una constante definida en un archivo de encabezado

#define THIS_CONST 'A' 

Quiero escribir esta constante en una secuencia. Hago algo como

 char c = THIS_CONST; write(fd, &c, sizeof(c)) 

Sin embargo, lo que me gustaría hacer por brevedad y claridad es:

 write(fd, &THIS_CONST, sizeof(char)); // error // lvalue required as unary '&' operand 

¿Alguien sabe de alguna macro / otro truco para obtener un puntero a un literal? Me gustaría algo que pueda ser usado así:

 write(fd, PTR_TO(THIS_CONST), sizeof(char)) 

Nota: Me doy cuenta de que podría declarar mis constantes como variables constantes estáticas, pero luego no puedo usarlas en declaraciones de cambio / caso. es decir

 static const char THIS_CONST = 'A' ... switch(c) { case THIS_CONST: // error - case label does not reduce to an integer constant ... } 

¿A menos que haya una manera de usar una variable const en una etiqueta de caso?

No hay manera de hacer esto directamente en C89. Tendrías que usar un conjunto de macros para crear tal expresión.

En C99, se permite declarar literales de estructura o unión, y los inicializadores a escalares se pueden escribir usando una syntax similar. Por lo tanto, hay una manera de lograr el efecto deseado:

 #include  void f(const int *i) { printf("%i\n", *i); } int main(void) { f(&(int){1}); return 0; } 

La única forma de obtener un puntero es colocando el literal en una variable (su primer ejemplo de código). Luego puede usar la variable con write() y el literal in switch .

C simplemente no permite la dirección de literales de caracteres como ‘A’. Para lo que vale, el tipo de caracteres literales en C es int (char en C ++ pero esta pregunta está etiquetada como C). ‘A’ tendría un valor definido de implementación (como 65 en sistemas ASCII). Tomar la dirección de un valor no tiene ningún sentido y no es posible.

Ahora, por supuesto, puede tomar la dirección de otros tipos de literales, como los literales de cadena, por ejemplo, lo siguiente está bien:

 write(fd, "potato", sizeof "potato"); 

Esto se debe a que la cadena literal “potato” es una matriz, y su valor es un puntero a la ‘p’ al comienzo.

Para elaborar / aclarar, solo puede tomar la dirección de los objetos. es decir, el operador & (dirección-de) requiere un objeto, no un valor.

Y para responder a la otra pregunta que no entendí, C no permite tags de casos no constantes, y esto incluye variables declaradas const.

Dado que llamar a write () para escribir un solo carácter en un descriptor de archivo es casi seguro que mata el rendimiento, es probable que desee hacer solo fputc (THIS_CONST, flujo).

 #define THIS_CONST 'a' 

Es solo una macro. Básicamente, el comstackdor solo inserta ‘a’ en todos los lugares donde se usa THIS_CONST. Tu podrías intentar:

 const char THIS_CONST = 'a'; 

Pero sospecho que no funcionará con Wither (no tengo un comstackdor c a mano para probarlo, y han pasado varios años desde que escribí el código c).

simplemente use una constante de cadena, que es un puntero a un carácter, y luego solo escriba 1 byte:

 #define MY_CONST_STRING "A" write(fd, MY_CONST_STRING, 1); 

Tenga en cuenta que el byte ‘\ 0’ al final de la cadena no se escribe.

Puede hacer esto para todo tipo de valores constantes, simplemente use la cadena de código hexadecimal apropiada, por ejemplo

 #define MY_CONST_STRING "\x41" 

También le dará el carácter ‘A’. Para cosas de múltiples bytes, tenga cuidado de usar la endianidad correcta.

Digamos que desea tener un puntero a un INT_MAX, que es, por ejemplo, 0x7FFFFFFF en un sistema de 32 bits. Entonces puedes hacer lo siguiente:

 #define PTR_TO_INT_MAX "\xFF\xFF\xFF\x7F" 

Se puede ver que esto funciona pasándolo como un puntero sin referencia a printf:

 printf ("max int value = %d\n", *(int*)PTR_TO_INT_MAX); 

que debe imprimir 2147483647.

Estas respuestas están todas desactualizadas y, aparte de un comentario, nadie se refiere a las actualizaciones de idiomas recientes.

En un comstackdor C99-C11 que usa un literal compuesto, http://en.cppreference.com/w/c/language/compound_literal , es posible crear un puntero a una constante sin nombre, como en:

 int *p = &((int){10}); 

Para los caracteres, puede usar variables estáticas globales adicionales. Quizás algo como:

 #define THIS_CONST 'a' static char tmp; #define PTR_TO(X) ((tmp = X),&tmp) write(fd,PTR_TO(THIS_CONST),sizeof(char)); 

No hay razón para que el comstackdor tenga que poner el literal en cualquier ubicación de memoria, por lo que su pregunta no tiene sentido. Por ejemplo, una statement como

 int a; a = 10; 

probablemente solo se traduciría directamente a “poner un valor diez en un registro”. En la salida en lenguaje ensamblador del comstackdor, el valor diez en sí nunca existe como algo en la memoria al que se podría apuntar, excepto como parte del texto del progtwig real.

No puedes llevarle un puntero.

Si realmente quieres una macro para obtener un puntero,

 #include  static char getapointer[1]; #define GETAPOINTER(x) &getapointer, getapointer[0] = x int main () { printf ("%d\n",GETAPOINTER('A')); } 

Puedo ver lo que estás tratando de hacer aquí, pero estás tratando de usar dos cosas fundamentalmente diferentes aquí. El quid de la cuestión es que las declaraciones de case necesitan usar valores que están presentes en el momento de la comstackción , pero los punteros a los datos en la memoria están disponibles solo en el tiempo de ejecución .

Cuando haces esto:

 #define THIS_CONST 'A' char c = THIS_CONST; write(fd, &c, sizeof(c)) 

estas haciendo dos cosas Está haciendo que la macro THIS_CONST esté disponible para el rest del código en el momento de la comstackción, y está creando un nuevo char en tiempo de ejecución que se inicializa a este valor. En el punto en el que se ejecuta la línea de write(fd, &c, sizeof(c)) , el concepto de THIS_CONST ya no existe, por lo que ha identificado correctamente que puede crear un puntero a c , pero no un puntero a THIS_CONST .

Ahora, cuando haga esto: static const char THIS_CONST = ‘A’; switch (c) {caso THIS_CONST: // error – la etiqueta del caso no se reduce a una constante entera …}

está escribiendo código donde el valor de la statement de caso debe evaluarse en el momento de la comstackción. Sin embargo, en este caso, ha especificado THIS_CONST de una manera en la que es una variable y, por lo tanto, su valor solo está disponible en tiempo de ejecución a pesar de que “sepa” que va a tener un valor particular . Ciertamente, otros idiomas permiten que sucedan cosas diferentes con las declaraciones de casos, pero esas son las reglas con C.

Esto es lo que sugeriría:

1) No llamar a una variable THIS_CONST . No hay ninguna razón técnica para no hacerlo, pero la convención sugiere que esta es una macro en tiempo de comstackción, y no debes confundir a tus lectores.

2) Si desea que los mismos valores estén disponibles en tiempo de comstackción y en tiempo de ejecución, encuentre una forma adecuada de mapear macros de tiempo de comstackción en variables de tiempo de ejecución. Esto puede ser tan simple como:

 #define CONST_STAR '*' #define CONST_NEWLINE '\n' static const char c_star CONST_STAR; static const char c_newline CONST_NEWLINE; 

Entonces puedes hacer:

 switch(c) { case CONST_STAR: ... write(fd, &c_star, sizeof(c_star)) ... } 

(Tenga en cuenta también que sizeof(char) siempre es uno, por definición. Puede que ya lo sepa, pero no es tan apreciado como quizás debería ser).

Ok, he ideado un poco de pirateo, solo para caracteres, pero lo pondré aquí para ver si inspira soluciones mejores de alguien más.

 static const char *charptr(char c) { static char val[UCHAR_MAX + 1]; val[(unsigned char)c] = c; return &val[(unsigned char)c]; } ... write(fd, charptr(THIS_CONST), sizeof(char));