test example else c inline

c - example - jstl if null



definición múltiple de función en línea (6)

El error de compilación que ves es en realidad un error de vinculador.

gcc y g ++ tratan la static inline un poco diferente. inline fue la primera parte de C ++ y luego se convirtió en una extensión para muchos compiladores de C, antes de agregarse al estándar C. La semántica estándar podría ser diferente, pero solo podrían ser las implementaciones diferentes.

También podría tener algo que ver con algunas cosas locas que suceden con el código C ++ que se deshace de las cosas de plantillas duplicadas que también capturan otras cosas duplicadas.

He revisado algunas publicaciones relacionadas con este tema, pero no pude resolver completamente mis dudas. Esta podría ser una pregunta muy ingenua.

Tengo un archivo de encabezado inline.h y dos unidades de traducción main.cpp y tran.cpp .

Los detalles del código son los siguientes

inline.h

#ifndef __HEADER__ #include <stdio.h> extern inline int func1(void) { return 5; } static inline int func2(void) { return 6; } inline int func3(void) { return 7; } #endif

C Principal

#define <stdio.h> #include <inline.h> int main(int argc, char *argv[]) { printf("%d/n",func1()); printf("%d/n",func2()); printf("%d/n",func3()); return 0; }

tran.cpp

//(note that the functions are not inline here) #include <stdio.h> int func1(void) { return 500; } int func2(void) { return 600; } int func3(void) { return 700; }

El código anterior se compila en g ++, pero no se compila en gcc (incluso si realiza cambios relacionados con gcc, como cambiar el código a .c, sin usar ningún archivo de encabezado de C ++, etc.). El error que se muestra es "definición duplicada de función en línea - func3".

¿Puede aclarar por qué esta diferencia está presente en los compiladores?

Además, cuando ejecuta el programa (g ++ compilado) creando dos unidades de compilación separadas ( main.o y tran.o ) y crea un ejecutable a.out , la salida obtenida es:

500
6
700

¿Por qué el compilador recoge la definición de la función que no está en línea? En realidad, dado que #include se usa para "agregar" la definición en línea, esperaba 5,6,7 como salida. Mi entendimiento fue durante la compilación desde que se encontró la definición en línea, la llamada a la función sería "reemplazada" por la definición de la función en línea.

¿Podría por favor decirme en pasos detallados el proceso de compilación y enlace que nos llevaría a 500,6,700 salida? Solo puedo entender la salida 6.


El error de compilación se debe a que existe una definición duplicada de func1 ();

Debido a que func1 () se define usando extern inline, producirá una definición externa.

Sin embargo, también hay una definición externa en tran.c, que causa un error de definición múltiple.

Sin embargo, func2 () y func3 () no producen una definición externa, por lo tanto, no hay error de redefinición.

Es posible que desee consultar here here .

Además, tome nota de que c ++ y c trata las funciones en línea de manera diferente, e incluso en c, diferentes estándares (c89 vs. c99) trata las funciones en línea de manera diferente.


Esta respuesta se divide en las siguientes secciones:

  1. Cómo reproducir la duplicate definition of inline function - func3 problema duplicate definition of inline function - func3 y por qué.
  2. Por qué la definición de func3 es un duplicado en lugar de func1 .
  3. ¿Por qué compila usando g++

Cómo producir la definición duplicada de la función en línea - problema func3

El problema puede ser reproducido exitosamente por

  1. Renombrar tran.cpp a tran.c
  2. Compilar con gcc -o main main.c tran.c

@ K71993 en realidad está compilando usando la antigua semántica en línea de gnu89, que es diferente de C99. La razón para cambiar el nombre de tran.cpp a tran.c es decirle al controlador gcc que lo trate como fuente C lugar de fuente C++ .

Por qué la definición de func3 es un duplicado en lugar de func1.

Semántica en línea de GNU 89

El siguiente texto se cita del documento de GCC: una función en línea es tan rápida como una macro explica por qué func3 es una definición duplicada en lugar de func1 , ya que func3 (en lugar de func1 ) es un símbolo visible externamente (en la semántica en línea GNU89)

Cuando una función en línea no es estática, el compilador debe asumir que puede haber llamadas de otros archivos de origen; Como un símbolo global solo se puede definir una vez en cualquier programa, la función no debe definirse en los otros archivos de origen, por lo que las llamadas no se pueden integrar. Por lo tanto, una función en línea no estática siempre se compila por sí misma de la manera habitual.

Si especifica tanto inline como extern en la definición de la función , entonces la definición se usa solo para inline. En ningún caso, la función se compila por sí sola, ni siquiera si hace referencia a su dirección explícitamente. Dicha dirección se convierte en una referencia externa, como si solo hubiera declarado la función y no la hubiera definido.

Semántica en línea C99

Si se compila con el estándar C99, es decir, gcc -o main main.c tran.c -std=c99 , el vinculador se quejará de que la definición de func1 es un duplicado debido a la razón por la que extern inline en C99 es una definición externa como se menciona en Otras publicaciones y comentarios.

Consulte también this excelente respuesta sobre las diferencias semánticas entre GNU89 inline y C99 inline.

Por qué se compila utilizando g++ .

Cuando se compila con g++ , el programa fuente se considera como fuente C++ . Dado que func1 , func2 y func3 se definen en múltiples unidades de traducción y sus definiciones son diferentes, se viola la Regla de una sola definición de C ++ . Dado que no se requiere que el compilador genere mensajes dignosticados cuando las definiciones abarcan varias unidades de traducción, el comportamiento no está definido.


Su código no es válido desde el punto de vista de C ++, ya que viola flagrantemente la Regla de una definición. La única razón por la que logró compilarlo con el compilador de C ++ es la comprobación de errores sueltos en su compilador de C ++ (resulta ser una de esas partes de ODR donde "no se requiere diagnóstico").

Su código no es válido C, porque proporciona una definición externa duplicada de la función func1 . Tenga en cuenta que es func1 , no func3 que es problemático desde el punto de vista de C. No hay nada formalmente incorrecto con tu func3 . Su func2 también está bien, siempre y cuando las dos definiciones nunca se "encuentren" en la misma unidad de traducción.

"Una posible razón por la que puede obtener un informe de diagnóstico diferente de su compilador es que su compilador C podría admitir funciones en inline de alguna manera no estándar específica del compilador (ya sea un compilador pre-C99 o un compilador moderno ejecutado en no estándar" modo "heredado).

Francamente, me resulta difícil creer que esté recibiendo un informe de errores sobre la función func3 de cualquier compilador, suponiendo que el código que publicó representa con precisión lo que está tratando de compilar. Lo más probable es que lo que publicaste no sea el código real.


Tal vez debería publicar el código real. Los fragmentos que muestres no se compilan:

  • inline.h tiene extern inline int func1(void) Eso no tiene ningún sentido.
  • main.h tiene #define <stdio.h> Creo que quiso decir include lugar.

Una vez que los arreglé y compilé con gcc, se compiló bien y obtuve el siguiente resultado

5 6 7

Cuando compilo con g ++, obtengo esta salida:

5 6 700

Eso sucede porque func3 () no es estático en inline.h


básicamente Inline es una entrada tardía a GCC (me refiero a compilador c). "[...] Una definición en línea no proporciona una definición externa para la función, y no prohíbe una definición externa en otra unidad de traducción. Una definición en línea proporciona una alternativa a una definición externa, que un traductor puede usar para implementar cualquier definición. llamada a la función en la misma unidad de traducción. No se especifica si una llamada a la función utiliza la definición en línea o la definición externa ". - ISO 9899: 1999 (E), la norma C99, sección 6.7.4