Was ist der Unterschied zwischen __attribute__((const))
und __attribute__((pure))
in GNU-C?
__attribute__((const)) int f() {
/* ... */
return 4;
}
vs
__attribute__((pure)) int f() {
/* ... */
return 4;
}
Was ist der Unterschied zwischen __attribute__((const))
und __attribute__((pure))
in GNU-C?
__attribute__((const)) int f() {
/* ... */
return 4;
}
vs
__attribute__((pure)) int f() {
/* ... */
return 4;
}
Paul R
Von dem Dokumentation für den ARM-Compiler (basiert auf gcc):
__attribute__((pure))
Funktionsattribut
Viele Funktionen haben keine Wirkung, außer einen Wert zurückzugeben, und ihr Rückgabewert hängt nur von den Parametern und globalen Variablen ab. Funktionen dieser Art können einer Datenflussanalyse unterzogen und gegebenenfalls eliminiert werden.
__attribute__((const))
Funktionsattribut
Viele Funktionen untersuchen nur die an sie übergebenen Argumente und haben außer dem Rückgabewert keine Auswirkungen. Dies ist eine viel strengere Klasse als__attribute__((pure))
, da eine Funktion den globalen Speicher nicht lesen darf. Wenn bekannt ist, dass eine Funktion nur mit ihren Argumenten arbeitet, dann kann sie einer gemeinsamen Unterausdruckseliminierung und Schleifenoptimierung unterzogen werden.
Also, TL;DR: __attribute__((const))
ist das gleiche wie __attribute__((pure))
aber ohne Zugriff auf globale Variablen.
Beachten Sie, dass der ARM-Compiler auch eine __pure
Funktionsqualifizierer, der strenger ist als der pure
Attribut und entspricht dem const
Attribut.
– jap
31. Januar 2017 um 8:40 Uhr
Erwähnenswert ist auch der Hinweis zu Zeigerargumenten in der GCC-Dokumentation: Note that a function that has pointer arguments and examines the data pointed to must not be declared const
– Ursprung
7. März 2017 um 16:44 Uhr
@origo IMO const wäre in Ordnung, wenn der Zeiger auf schreibgeschützte Daten zeigt, z. B. wenn es sich um ein Zeichenfolgenliteral handelt.
– rockdaboot
8. Mai 2019 um 12:43 Uhr
Antti Haapala – Слава Україні
Der Unterschied wird in der erklärt GCC-Handbücher. Vor allem a const
Die Funktion darf nur die übergebenen Argumente und keinen Speicher verwenden, während a pure
Die Funktion kann unter Einschränkungen auch auf den Speicher zugreifen:
Das Attribut pure verbietet einer Funktion, den beobachtbaren Zustand des Programms auf andere Weise als durch die Untersuchung des Rückgabewerts der Funktion zu ändern. Mit dem Attribut pure deklarierte Funktionen können jedoch alle nichtflüchtigen Objekte sicher lesen und den Wert von Objekten so ändern, dass der Rückgabewert oder der beobachtbare Zustand des Programms nicht beeinflusst werden.
Das __attribute__ ((pure))
bedeutet, dass die Funktion keine Seiteneffekte hat und der zurückgegebene Wert von den Argumenten und dem Zustand der globalen Variablen abhängt. Daher ist es für den Optimierer sicher, einige Aufrufe zu eliminieren, wenn die Argumente gleich sind, und die Der Anrufer hat zwischen den Anrufen nichts getan, um den Status der Globals zu ändern.
Das __attribute__ ((const))
bedeutet, dass der Rückgabewert ausschließlich eine Funktion der Argumente ist, und wenn eines der Argumente Zeiger sind, dann die Zeiger darf nicht dereferenziert werden.
EIN const
Funktion ist immer pure
.
Beispiele von const
Funktionen wären das abs
Funktionen ab <stdlib.h>
und einige mathematische Funktionen aus <math.h>
: sqrt
, exp
usw. (obwohl sie Rundungsmodi unterliegen können).
Beispiele von pure
aber nicht konstante Funktionen wären solche Funktionen wie strlen
– da es den übergebenen Zeiger dereferenziert.
Gemessen an dem, was der Optimierer tut, greift eine reine Funktion möglicherweise nicht auf globale Variablen zu, deren Zustand durch Faktoren geändert werden kann, die außerhalb des Kontrollflusses liegen, in dem die reine Funktion erscheint. Also globale Variablen, die einem Gerätezustand zugeordnet sind, oder solche, die von einem anderen Thread geändert werden könnten, und so weiter.
– Allmächtig
22. Februar 2019 um 3:01 Uhr
Ja, der Unterschied zwischen den 2 besteht eher darin, dass eine reine Funktion ihren Rückgabewert ändern kann, wenn der Aufrufer eine globale Änderung vorgenommen hat
– Antti Haapala – Слава Україні
22. Februar 2019 um 4:44 Uhr
Schließlich ist das Attribut ein Signal für den Aufrufer, und der Aufrufer kann nicht den Zustand aller existierenden Memory-Mapped-Variablen kennen 😀
– Antti Haapala – Слава Україні
22. Februar 2019 um 4:49 Uhr
Neue Formulierung: “und Anrufer hat zwischen den Anrufen nichts getan, um den Status der Globals zu ändern.”
– Antti Haapala – Слава Україні
22. Februar 2019 um 4:50 Uhr
Argh link b0rken. @Omnifarious Anscheinend hat es sich kürzlich geändert und ist viel besser als zu der Zeit, als ich die Antwort geschrieben habe. Dies ist die von der Zeit, als ich die Frage beantwortete
– Antti Haapala – Слава Україні
22. Februar 2019 um 5:23 Uhr
Beachten Sie, dass, wenn einer Funktion ein Zeiger übergeben wird und der Kontext dieses Zeigers untersucht wird, sie nicht deklariert werden kann const
auch wenn der übergebene Zeiger und der Zeiger Kontexte sind const
. Dies ist eine starke Einschränkung der Nützlichkeit von const
.
Sie können mehrere Werte in C zurückgeben, indem Sie eine Struktur verwenden, was die Verwendung vereinfacht pure
. (Es ist üblicher, Zeigerrückgabeoperanden zu verwenden, aber dies unterbricht die Verwendung von pure
).
Dies kann helfen.
– Hacken
18. März 2015 um 9:16 Uhr
Siehe auch Implikationen reiner und konstanter Funktionen auf LWN.
– jww
30. Juli 2018 um 12:49 Uhr