Kann jemand erklären, was sie sind und warum ich sie brauchen würde? Welche Art von Anwendungen erstelle ich, wenn ich Intrinsics verwenden muss?
Antworten:
Normalerweise bezieht sich "intrinsics" auf Funktionen, die integriert sind - dh die meisten Standardbibliotheksfunktionen, die der Compiler inline generieren kann / wird, anstatt eine tatsächliche Funktion in der Bibliothek aufzurufen. Zum Beispiel könnte ein Aufruf wie: memset(array1, 10, 0)
für ein x86 wie folgt kompiliert werden:
mov ecx, 10
xor eax, eax
mov edi, offset FLAT:array1
rep stosb
Solche Eigenheiten sind lediglich eine Optimierung. Das "Benötigen" von Intrinsics ist höchstwahrscheinlich eine Situation, in der der Compiler Intrinsics unterstützt, mit denen Sie Code generieren können, den der Compiler nicht direkt generieren kann (oder normalerweise nicht). Ein offensichtliches Beispiel: Einige Compiler für x86 verfügen über "MMX Intrinsics", mit denen Sie "Funktionen" verwenden können, die eigentlich nur direkte Darstellungen von MMX-Anweisungen sind.
Eine intrinsische Funktion ist eine Funktion, die der Compiler nach Möglichkeit direkt implementiert, anstatt sie mit einer von der Bibliothek bereitgestellten Implementierung der Funktion zu verknüpfen.
Ein häufiges Beispiel ist strncpy()
.
Bei kurzen Zeichenfolgen nimmt das Aufrufen eines Funktionsaufrufs strncpy()
, bei dem ein 'Stapelrahmen' mit einer Rücksprungadresse eingerichtet wird, mehr Zeit in Anspruch als das eigentliche Kopieren von Bytes. Schlimmer noch, die Auswirkung auf CPU-Pre-Fetch-Puffer blockiert die CPU-Ausführung für mehrere Taktzyklen.
Stattdessen wird die intrinsische Funktion vom Compiler anstelle eines Funktionsaufrufs implementiert. Im Beispiel von strncpy()
wird der Bytekopiercode direkt an der Stelle ausgegeben, an der er strncpy()
aufgerufen wird.
Ähnlich wie in diesem strncpy()
Beispiel wird jede intrinsische Funktion direkt als Inline-Code implementiert, wenn die erforderlichen Einschränkungen erfüllt sind.
Eine nicht-intrinsische Kopie der intrinsischen Funktion ist normalerweise noch in der Standardbibliothek vorhanden, falls die Adresse der Funktion benötigt wird.
Im Vergleich zu Inline-Funktionen wird die intrinsische Funktion vom Compiler bereitgestellt. Es gibt weder eine Stelle im Quellcode eines C-Programms, an der die intrinsische Funktion geschrieben ist, noch eine Bibliotheksimplementierung, mit der verknüpft werden muss. Eine Inline-Funktion unterscheidet sich darin, dass der Compiler den Quellcode für die Inline-Funktion liest, ähnelt jedoch darin, dass er später möglicherweise eine kompilierte Übersetzung der Inline-Funktion direkt in den Objektcode ausgibt, wobei der Overhead eines Funktionsaufrufs entfällt.
Kurz gesagt, der praktische Unterschied zwischen einer intrinsischen Funktion und einer Inline-Funktion besteht darin, dass intrinsische Funktionen "vorhanden" sind, selbst wenn Sie nicht über #include
die erforderliche Header-Datei verfügen, die die Funktionsdeklaration enthält. Für eine Inline-Funktion muss die Header-Datei mit der Funktionsdeklaration zuerst #include
'd (oder anderweitig deklariert) sein.
Intrinsics werden vom Compiler als Funktionen verfügbar gemacht, die per se nicht Teil einer Bibliothek sind .
Diejenigen, die Sie wahrscheinlich am häufigsten verwenden würden, sind Assembly-Intrinsics, die vom Compiler als genau die Maschinenanweisung behandelt werden, die sie darstellen. Sie würden sie beispielsweise in Code verwenden, in dem Sie einen bestimmten CPU-Befehl nutzen müssen, den der Compiler nicht automatisch generiert, und in dem Sie nicht unbedingt einen vollständigen Inline-Assembly-Abschnitt benötigen.
Intrinsics sind die Merkmale einer Sprache, die ein Compiler erkennt und implementiert, ohne dass das Programm sie deklarieren muss. Der Compiler kann eine Verknüpfung zu einer Laufzeitbibliothek herstellen oder nicht, um den Vorgang auszuführen. In C ++ ist die Strukturkopieroperation beispielsweise implizit:
struct {
int a;
char b [100];
long c [27];
} s, t;
...
s = t; // this statement copies hundreds of bytes, likely with a rtl call
Andere Beispiele sind Sprachen wie Fortran, in denen der komplexe Typ implizit unterstützt wird und die transzendentalen Funktionen (Sinus, Tangens usw.) nicht deklariert werden müssen und können. PHP, Javascript, Ruby usw. verfügen über Hunderte von Funktionen, mit denen Sie Arrays erstellen und durchsuchen, Übereinstimmungen mit regulären Ausdrücken durchführen usw. usw.
Bei Ihren anderen Fragen besteht der einzige Unterschied darin, ob sie deklariert werden müssen. Beispielsweise muss ein C ++ - Programm, das transzendentale Funktionen verwendet, Deklarationen der Mathematikbibliothek enthalten:
#include <math.h>
Es gibt kein bestimmtes Anwendungsmuster, das von den Eigenschaften abhängt. Dies ist nur für Compiler-Autoren und Programmierer von Bedeutung.