Qual è la differenza tra una funzione di libreria e una funzione build-in?
Una funzione incorporata è quella che il compilatore ha una certa conoscenza direttamente all'interno del compilatore stesso. Una funzione di libreria è semplicemente quella definita in una libreria. Possono esistere sia una funzione incorporata che una funzione di libreria con lo stesso nome, quindi per il resto delle tue domande tratterò la "funzione di libreria" come "funzione di libreria che non è una funzione incorporata".
C'è qualcosa che una funzione built-in può fare ma una funzione di libreria non può?
Sì. Una funzione built-in può scegliere, per esempio, non per valutare i suoi argomenti:
int main() {
int i = 0;
__builtin_constant_p (++i); // checks whether ++i is a constant expression
// does not evaluate ++i
return i; // returns 0
}
Questo perché una funzione built-in può essere trasformato dal compilatore in qualcos'altro, che in realtà non ha bisogno di contenere qualsiasi chiamata di funzione.
Posso scrivere una funzione di libreria che esegue lo stesso compito della funzione di stampa in funzione?
C'è una conoscenza integrata di printf
, ma per la maggior parte, questo è perfettamente fattibile. Scopri come usare <stdarg.h>
.
Come è possibile indicare il tipo di parametri di input (% f, float o double)?
È necessario fidarsi del chiamante affinché la stringa di formato corrisponda agli argomenti rimanenti; non è possibile rilevare qualcosa come il passaggio di un int
quando la stringa di formato si aspetta un double
. Ma non è necessario gestire la differenza tra float
e double
, perché è impossibile passare un float
a printf
: verrà convertito in double
(indipendentemente dalla stringa di formato) prima che lo veda lo printf
. I requisiti di printf
sono stati accuratamente realizzati per evitare qualsiasi necessità di magia del compilatore.
Le istruzioni della macchina delle funzioni GCC build-in non sono memorizzate in una libreria, giusto?
Le chiamate alle funzioni integrate vengono trasformate in fase di compilazione, ma tale trasformazione può essere semplicemente il risultato di una chiamata a una funzione di libreria con lo stesso nome.
Dove sono?
Se la trasformazione viene eseguita in fase di compilazione, non sono disponibili istruzioni sulla macchina. La chiamata viene trasformata in un codice diverso e tale codice viene quindi compilato per produrre istruzioni sulla macchina. Se il risultato è una chiamata a una funzione di libreria, le istruzioni macchina per quella funzione di libreria fanno parte della libreria.
Quando si effettua il collegamento, come è possibile controllare dove inserire questi codici funzione incorporati?
Non capisco cosa intendi qui. Una chiamata a una funzione built-in viene trasformata in fase di compilazione su un codice diverso e tale codice diverso viene quindi compilato come parte della funzione che contiene la chiamata. Sarà messo ovunque verrà messo il resto del codice di quella funzione contenente.
Perché a volte riesco a messaggi di errore del tipo "undefined reference to __builtin_stdarg_start" quando si fa il collegamento
non esiste alcuna funzione built-in __builtin_stdarg_start
, nonostante il prefisso __builtin
, quindi questo è trattata come una chiamata a una funzione di libreria. Inoltre, non esiste alcuna funzione di libreria __builtin_stdarg_start
, quindi il linker lo rileva come un errore.
C'era una funzione incorporata __builtin_stdarg_start
, ma è stata rimossa anni fa e il codice non avrebbe mai dovuto usarlo in primo luogo.
gcc -c main.c, nm indica che non vi è alcun simbolo printf in main.o, (solo main (T) e puts (U)), perché?
Ecco perché printf
esiste sia come funzione incorporata che come funzione di libreria. La funzione built-in di solito chiama semplicemente la funzione di libreria, ma a volte è possibile fare di meglio, anche nell'esempio. In questo caso, la funzione integrata printf
può fornire il risultato corretto senza chiamare la funzione di libreria printf
.
(Si chiama built-in con una T) –
È possibile creare il proprio printf. Guarda l'intestazione di stdargs.h. – Mabus
GCC è (molto probabilmente) l'ottimizzazione di 'printf()' in 'puts()' perché stai passando una semplice stringa a 'printf()' senza ulteriori argomenti. Vedi: http://linux.die.net/man/3/puts – Thomas