C: ¿Son globales las directivas #define?

4 minutos de lectura

estoy algo confundido por #define declaraciones. En las bibliotecas, parecen ser un medio de comunicación entre diferentes archivos, con muchos #ifdefarena #ifndefs.

Habiendo dicho eso, ahora tengo dos archivos. file1.c y file2.c compilado junto con #define TEST 10 en el interior file2.c. Sin embargo, cuando uso TEST en el interior file2.c el compilador da el siguiente mensaje de error:

'TEST' undeclared (first use in this function)

Son #define directivas globales?

  • Depende de donde se definan.

    – Nick

    9 de mayo de 2012 a las 9:01

  • #define es una directiva de preprocesador, solo hace sustituciones de texto simples en tiempo de compilación, solo la unidad de compilación y cualquier #includelos archivos d ver a #define.

    – Pablo R.

    9 de mayo de 2012 a las 9:02


#defines no son globales, son solo una sustitución donde sea que se usen (si se declaran en la misma unidad de compilación)

Están no globales, son no símbolos, son irrelevante en la vinculación, solo son relevantes en pre-compilación.

  • ¿Qué quiere decir con “unidad de compilación”? como puedo tener file1.c y file.2 en la misma unidad de compilación?

    – azul aleatorio

    9 de mayo de 2012 a las 9:09

  • No. Se recopilan por separado. y gallina unidas entre sí. ¿Estás familiarizado con el proceso de compilación de C?

    – MByD

    9 de mayo de 2012 a las 9:12

  • Asi que file1.c y file2.c nunca puede estar en la misma unidad de compilación?

    – azul aleatorio

    9 mayo 2012 a las 10:00

  • básicamente – no. si desea compartir una macro entre ellos, colóquela en un archivo de encabezado e incluya ese encabezado en ambos archivos.

    – MByD

    9 de mayo de 2012 a las 10:02

  • @Randomblue: Piense en una “unidad de compilación” como “archivo ac, y todos los encabezados que incluye, y todos los encabezados que incluyen, etc., etc., etc., hasta que no haya más encabezados”. Este es un “fragmento” que compila el compilador. Después de que el compilador compila cada archivo c por separado, vincula esos resultados entre sí.

    – Pato mugido

    25/04/2017 a las 21:44

avatar de usuario
jamesdlin

#defineLas macros d son globales en el sentido de que no siguen las reglas normales de alcance de C. La sustitución textual de la macro se aplicará (casi) en cualquier sitio el nombre de la macro aparece después de su #define. (Las excepciones notables son si el nombre de la macro es parte de un comentario o parte de un literal de cadena).

Si define una macro en un archivo de encabezado, cualquier archivo que #includes ese archivo de encabezado heredará esa macro (ya sea que se desee o no), a menos que el archivo la anule explícitamente después con #undef.

En tu ejemplo, file2.c no sabe sobre el TEST macro. ¿Cómo sabría recoger el #define de file1.c? ¿Por magia? Dado que las macros realizan la sustitución textual en el código fuente, no hay representación de ellas en los archivos de objetos generados. file2.c por lo tanto, necesita saber esa regla de sustitución en sí misma, y ​​si desea que se comparta en varios archivos, eso #define necesita vivir en un archivo de encabezado común que su .c archivos #include.

Si está preguntando específicamente cuántos de los #ifdefs que ve en el trabajo de las bibliotecas, es probable que muchos de ellos se comparen con predefinido nombres de macro proporcionados por el entorno de compilación. Por ejemplo, un compilador C99 define un __STDC_VERSION__ macro que especifica la versión del idioma; un compilador de Microsoft define un _MSC_VER macro. (A menudo, estas macros predefinidas comienzan con guiones bajos iniciales, ya que esos nombres están reservados para el compilador).

Además, la mayoría de los compiladores permiten definir macros simples como argumentos de línea de comandos. Por ejemplo, puede compilar su código a través de gcc -DNDEBUG file1.c compilar file.c con NDEBUG definido para deshabilitar asserts.

  • Gracias por información útil

    usuario5066707

    25 de abril de 2017 a las 21:02

Por si alguien lee esto más tarde, y para añadir alguna información práctica:

  • Algunos entornos, como atmel, vs o iar, le permiten definir directivas #define globales. Básicamente pasan estos valores definidos al precompilador en algún formato de línea de comandos.
  • Puede hacer lo mismo en comandos por lotes o archivos MAKE, etc.
  • Arduino siempre agrega una variante de placa (generalmente ubicada en hardware\arduino\variants) a todas las compilaciones. En ese momento, puede crear un nuevo tablero que contenga sus directivas de definición global y usarlo de esa manera. Por ejemplo, puede definir una placa mega2560 (depuración) a partir de la mega2560 original que contiene algunas directivas de depuración. Agregará una referencia a esa variante en “boards.txt”, copiando y pegando algún texto y modificándolo correctamente.

Al final del día, tendrá que dar ese hfile global o directiva global al compilador de una forma u otra.

¿Ha sido útil esta solución?