c++ - compiler - gcc g++
Cómo GCC maneja la función incorporada (2)
¿Cuál es la diferencia entre una función de biblioteca y una función incorporada?
Una función incorporada es aquella en la que el compilador tiene algún conocimiento directamente dentro del mismo compilador. Una función de biblioteca es simplemente una definida en una biblioteca. Pueden existir una función incorporada y una función de biblioteca con el mismo nombre, por lo que, para el resto de sus preguntas, trataré la "función de biblioteca" como "función de biblioteca que no es una función incorporada".
¿Hay algo que pueda hacer una función incorporada pero no una función de biblioteca?
Sí. Una función incorporada puede elegir, por ejemplo, no evaluar sus argumentos:
int main() {
int i = 0;
__builtin_constant_p (++i); // checks whether ++i is a constant expression
// does not evaluate ++i
return i; // returns 0
}
Esto se debe a que el compilador puede transformar una función incorporada en otra cosa, que en realidad no necesita contener ninguna llamada de función.
¿Puedo escribir una función de biblioteca que realice la misma tarea que la función en la función printf?
Existe algún conocimiento incorporado de printf
, pero en su mayor parte, esto es perfectamente factible. Busque cómo usar <stdarg.h>
.
¿Cómo puedo saber el tipo de los parámetros de entrada (% f, float o double)?
Debe confiar en la persona que llama para que la cadena de formato coincida con los argumentos restantes; no se puede detectar algo como pasar un int
cuando la cadena de formato espera un double
. Pero no necesita manejar la diferencia entre float
y double
, porque es imposible pasar un float
a printf
: se convertirá en double
(independientemente de la cadena de formato) antes de que printf
vea. Los requisitos de printf
se han realizado cuidadosamente para evitar cualquier necesidad de magia de compilación.
Las instrucciones de máquina de las funciones integradas de GCC no se almacenan en una biblioteca, ¿verdad?
Las llamadas a funciones integradas se transforman en tiempo de compilación, pero esa transformación puede simplemente resultar en una llamada a una función de biblioteca del mismo nombre.
¿Dónde están?
Si la transformación se realiza en tiempo de compilación, no hay instrucciones de la máquina. La llamada se transforma en un código diferente, y ese código se compila para producir instrucciones de la máquina. Si el resultado es una llamada a una función de biblioteca, las instrucciones de la máquina para esa función de biblioteca son parte de la biblioteca.
Al realizar la vinculación, ¿cómo puede controlar dónde colocar estos códigos de función incorporados?
No entiendo lo que quieres decir aquí. Una llamada a una función incorporada se transforma en tiempo de compilación en un código diferente, y ese código diferente se compila como parte de la función que contiene la llamada. Se colocará dondequiera que se coloque el resto del código de la función que contiene.
¿Por qué a veces puedo enviar mensajes de error como "referencia indefinida a __builtin_stdarg_start" al hacer el enlace?
No hay una función __builtin_stdarg_start
, a pesar del prefijo __builtin
, por lo que esto se trata como una llamada a una función de biblioteca. Y tampoco hay una función de biblioteca __builtin_stdarg_start
, por lo que el enlazador detecta esto como un error.
Solía haber una función __builtin_stdarg_start
, pero fue eliminada hace años, y el código nunca debería haberla usado en primer lugar.
gcc -c main.c, nm muestra que no hay ningún símbolo printf en main.o, (solo main (T) y puts (U)), ¿por qué?
Esto se debe a que printf
existe tanto como una función incorporada como una función de biblioteca. La función incorporada normalmente simplemente llama a la función de biblioteca, pero a veces es posible hacerlo mejor, incluso en su ejemplo. En este caso, la función incorporada printf
puede dar el resultado correcto sin tener que llamar a la función de biblioteca printf
.
Tengo problemas para entender las funciones integradas de GCC y me siento muy confundido.
¿Cuál es la diferencia entre una función de biblioteca y una función incorporada?
¿Hay algo que pueda hacer una función incorporada pero no una función de biblioteca?
¿Puedo escribir una función de biblioteca que realice la misma tarea que la función incorporada printf? ¿Cómo puedo saber el tipo de los parámetros de entrada (% f, float o double)?
Las instrucciones de máquina de las funciones incorporadas de GCC no se almacenan en una biblioteca, ¿verdad? ¿Dónde están?
Al realizar la vinculación, ¿cómo puede controlar dónde colocar estos códigos de función incorporados?
¿Por qué a veces puedo enviar mensajes de error como "referencia indefinida a __builtin_stdarg_start" al hacer el enlace?
// main.c #include <stdio.h> int main(void) { printf("hello world!/n"); return 0; }
gcc -c main.c, nm muestra que no hay ningún símbolo printf en main.o, (solo main (T) y puts (U)), ¿por qué?
Existen aproximadamente dos tipos de incorporaciones: las que corresponden a las funciones de biblioteca estándar ( malloc
, printf
y strcpy
se tratan como integradas de manera predeterminada), y las que no tienen una contrapartida en la biblioteca estándar: piense en __builtin_expect
, __builtin_prefetch
, etc.
El primer tipo de incorporaciones están ahí para permitir que el compilador emita código optimizado en lugar de las llamadas correspondientes. Al conocer la semántica interna de cada una de las llamadas de la biblioteca estándar, el compilador puede decidir emitir una llamada a la función que reside en la biblioteca, o emitir un fragmento de código personalizado en su lugar, de modo que la semántica original Se conservan y el código se ejecuta mejor.
El segundo tipo de elementos integrados (también llamados "intrínsecos") habilita trucos y optimizaciones que difícilmente se pueden lograr con un código estático que reside en una biblioteca. Pueden traducirse en dar pistas a la CPU ( __builtin_prefetch
, __builtin_expect
), o mejorar el lenguaje C con una mejor introspección en tiempo de compilación ( __builtin_constant_p
, __builtin_types_compatible_p
), o proporcionar una interfaz independiente de la plataforma para algunos elementos de la arquitectura. __builtin_popcount
).