Pregunta

Anoche me hicieron una pregunta en C y no sabía la respuesta ya que no he usado mucho C desde la universidad, así que pensé que tal vez podría encontrar la respuesta aquí en lugar de simplemente olvidarme de ella.

Si una persona tiene una definición como:

#define count 1

¿Puede esa persona encontrar el nombre de la variable? count usando el 1 que esta dentro?

No lo pensé porque pensé que el conteo apuntaría al 1 pero no veo cómo el 1 podría apuntar hacia atrás para contar.

¿Fue útil?

Solución

La respuesta simple es no, no pueden.#Defines así son manejados por el preprocesador y solo apuntan en una dirección.Por supuesto, el otro problema es que ni siquiera el compilador lo sabría (ya que un "1" podría apuntar a cualquier cosa) varias variables pueden tener el mismo valor al mismo tiempo.

Otros consejos

Basándose en la respuesta de @Cade Roux, si usa un preprocesador #define para asociar un valor con un símbolo, el código no tendrá ninguna referencia al símbolo una vez que se haya ejecutado el preprocesador:

#define COUNT (1)
...
int myVar = COUNT;
...

Después de que se ejecute el preprocesador:

...
int myVar = (1);
...

Como otros han señalado, esto básicamente significa "no", por el motivo anterior.

¿Puede esa persona encontrar el nombre de la variable "count" usando el 1 que está dentro de ella?

No

Como estoy seguro de que alguien más elocuente y versado que yo señalará que las cosas #definidas no están compiladas en el código fuente, lo que tienes es una macro de preprocesador que revisará el código fuente y cambiará todas las instancias de 'count'. ' se encuentra con un '1'.

Sin embargo, para arrojar más luz sobre la pregunta que le hicieron, debido a que C es un lenguaje compilado hasta el código de máquina, nunca tendrá la reflexión y la introspección que tiene con un lenguaje como Java o C#.Todos los nombres se pierden después de la compilación, a menos que tenga un marco creado alrededor de su fuente/compilador para hacer algunas cosas ingeniosas.

Esperanza este ayuda.(disculpe el juego de palabras)

Desafortunadamente, esto no es posible.

#define Las declaraciones son instrucciones para el preprocesador, todas las instancias de count son reemplazados con 1.En tiempo de ejecución no hay ninguna ubicación de memoria asociada con count, por lo que el esfuerzo es obviamente inútil.

Incluso si utiliza variables, después de la compilación no quedarán restos de los identificadores originales utilizados en el programa.Por lo general, esto sólo es posible en lenguajes dinámicos.

Un truco utilizado en C es utilizar la sintaxis # en macros para obtener la cadena literal del parámetro de macro.

#define displayInt(val) printf("%s: %d\n",#val,val)
#define displayFloat(val) printf("%s: %d\n",#val,val)
#define displayString(val) printf("%s: %s\n",#val,val)

int main(){
  int foo=123;
  float bar=456.789;
  char thud[]="this is a string";

  displayInt(foo);
  displayFloat(bar);
  displayString(thud);

  return 0;
}

La salida debería verse similar a la siguiente:

foo: 123
bar: 456.789
thud: this is a string

#define count 1 es una muy mala idea, porque le impide nombrar variables o campos de estructura count.

Por ejemplo:

void copyString(char* dst, const char* src, size_t count) {
   ...
}

Su count La macro hará que el nombre de la variable sea reemplazado por 1, impidiendo que esta función compile:

void copyString(char* dst, const char* src, size_t 1) {
   ...
}

Las definiciones de C son una directiva de preprocesador, no una variable.El preprocesador revisará su archivo C y reemplazará el lugar donde escribe el recuento con lo que usted definió, antes de compilar.Mire las entradas del concurso C ofuscado para conocer algunos usos particularmente ilustrados de esta y otras directivas de preprocesador.

El punto es que no hay un "recuento" para señalar un valor "1".Es solo una operación simple/buscar reemplazo que sucede antes el código incluso está realmente compilado.

Dejaré esto editable para que alguien que realmente sepa C lo corrija.

count no es una variable.No tiene ningún almacenamiento asignado ni ninguna entrada en la tabla de símbolos.Es una macro que el preprocesador reemplaza antes de pasar el código fuente al compilador.

En caso de que no estés haciendo la pregunta correcta, hay una manera de obtener el nombre usando macros:

#define SHOW(sym) (printf(#sym " = %d\n", sym))
#define count 1

SHOW(count); // prints "count = 1"

El # El operador convierte un argumento de macro en una cadena literal.

#define es una directiva de preprocesador, como tal, no es una "variable"

Lo que tienes ahí en realidad no es una variable, es una directiva de preprocesador.Cuando compilas el código, el preprocesador revisará y reemplazará todas las instancias de la palabra "count" en ese archivo con 1.

Quizás se pregunte si lo sé. ¿Puedo encontrar que el conteo apunta a ello?No.Debido a que la relación entre los nombres y valores de las variables no es una biyección, no hay vuelta atrás.Considerar

int count = 1;
int count2 = 1;

perfectamente legal, pero ¿a qué debo decidirme?

En general, no.

En primer lugar, #define no es una variable, es una macro de preprocesador del compilador.

Para cuando la fase principal del compilador comienza a funcionar, el nombre ha sido reemplazado por el valor y el nombre "count" no existirá en ninguna parte del código compilado.

Para las variables, no es posible encontrar los nombres de las variables en el código C en tiempo de ejecución.Esa información no se guarda.A diferencia de lenguajes como Java o C#, C no guarda muchos metadatos, en compilaciones hasta lenguaje ensamblador.

Las directivas que comienzan con "#" son manejadas por el preprocesador, que generalmente realiza la sustitución de texto antes de pasar el código al compilador "real".Como tal, no existe una variable llamada recuento, es como si todas las cadenas de "recuento" en su código se reemplazaran mágicamente con la cadena "1".

Entonces, no, no hay forma de encontrar esa "variable".

En el caso de una macro, ésta se preprocesa y se compila el resultado resultante.Por lo tanto, no hay forma alguna de averiguar ese nombre porque después de que el preprocesador termine su trabajo, el archivo resultante contendrá '1' en lugar de 'recuento' en todas partes del archivo.

Por tanto, la respuesta es no.

Si están mirando el código fuente C (que estarán en un depurador), verán algo como

int i = count;

en ese punto, pueden buscar hacia atrás y encontrar la línea

#define count 1

Sin embargo, si todo lo que tienen es la variable iDontKnowWhat y pueden ver que contiene 1, no hay forma de rastrearla hasta "contar".

¿Por qué?Porque #define se evalúa en el momento del preprocesador, lo que ocurre incluso antes de la compilación (aunque para casi todos, puede verse como la primera etapa de la compilación).En consecuencia, el código fuente es lo único que tiene información sobre el "recuento", como saber si alguna vez existió.Para cuando el compilador echa un vistazo, cada referencia a "recuento" ha sido reemplazada por el número "1".

No es un puntero, es solo una sustitución de cadena/token.El preprocesador reemplaza todos los #defines antes de que se compile el código.La mayoría de los compiladores incluyen un argumento -E o similar para emitir código precompilado, de modo que pueda ver cómo se ve el código después de procesar todas las #directivas.

Más directamente a su pregunta, no hay forma de saber si se está reemplazando un token en el código.Su código ni siquiera puede distinguir entre (count == 1) y (1 == 1).

Si realmente desea hacer eso, podría ser posible utilizar el análisis de texto del archivo fuente, por ejemplo, utilizando una herramienta de diferencias.

¿Qué quieres decir con "encontrar"?

La línea

#define count 1

define un símbolo "recuento" que tiene valor 1.

El primer paso del proceso de compilación (llamado preprocesamiento) reemplazará cada aparición del recuento de símbolos con 1, de modo que si tiene:

if (x > count) ...

será reemplazado por:

if (x > 1) ...

Si entiende esto, podrá ver por qué "hallar el recuento" no tiene sentido.

La persona que hizo la pregunta (¿fue una pregunta de una entrevista?) puede haber estado tratando de que usted diferencie entre el uso de constantes #define y enumeraciones.Por ejemplo:

#define ZERO 0
#define ONE 1
#define TWO 2

vs

enum {
  ZERO,
  ONE,
  TWO
};

Dado el código:

x = TWO;

Si usa enumeraciones en lugar de #defines, algunos depuradores podrán mostrarle la forma simbólica del valor, DOS, en lugar de solo el valor numérico de 2.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top