Ich muss einige Methoden implementieren, die mit verschiedenen Arten von Zahlenarrays arbeiten. Normalerweise würde ich für diesen Job Generics verwenden, aber da C sie nicht bereitstellt, versuche ich jetzt, sie mit Makros zu emulieren.
Hier ist ein Beispiel dafür, was ich versuche:
#ifndef TYPE
#define TYPE int
#endif
TYPE get_minimum_##TYPE (TYPE * nums, int len){
TYPE min = nums[0];
for (int i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Dies wird jedoch nicht kompiliert. Die Clang-Fehlermeldung:
Fehler: erwartet ‘;’ nach Deklarator der obersten Ebene
Gibt es eine Möglichkeit, dies in C zu tun? Oder muss ich das für jeden Typ per Hand umsetzen?
Wenn Sie etwas mehr über “Vorlagen”/”Generika” in C lesen möchten, können Sie diese Frage lesen. Es gibt einige interessante Antworten 🙂
– Jehan
13. Mai 2013 um 13:33 Uhr
Paul R
Sie können in einer Header-Datei so etwas tun:
//
// generic.h
//
#define TOKENPASTE(x, y) x ## y
#define GET_MINIMUM(T) TOKENPASTE(get_minimum_, T)
TYPE GET_MINIMUM (TYPE) (TYPE * nums, size_t len){
TYPE min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
und dann #include es in einer Quelldatei für jeden erforderlichen Typ, zB:
//
// generic.c
//
#define TYPE int
#include "generic.h"
#undef TYPE
#define TYPE float
#include "generic.h"
#undef TYPE
Sie können dies testen, indem Sie es über den Präprozessor ausführen:
$ gcc -E generic.c
int get_minimum_int (int * nums, size_t len){
int min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
float get_minimum_float (float * nums, size_t len){
float min = nums[0];
for (size_t i = 1; i < len; i++) {
if (nums[i] < min) {
min = nums[i];
}
}
return min;
}
Funktioniert das auch mit Strukturdefinitionen?
– Rafaelplayerxd YT
6. August um 17:42 Uhr
@RafaelplayerxdYT: Es hängt davon ab, was Sie mit Ihren verschiedenen Strukturtypen erreichen möchten?
– PaulR
7. August um 7:40 Uhr
Jehan
Eigentlich ist das Beste, was Sie tun können, ein Makro zu definieren, das die Funktion für den angegebenen Typ generiert.
#define define_get_minimum(T) \
T get_minimum_##T(T* nums, int len){ \
T min = nums[0]; \
for (int i = 1; i < len; i++) { \
if (nums[i] < min) { \
min = nums[i]; \
} \
} \
return min; \
}
Dann können Sie dieses Makro aufrufen, um die benötigten Spezialisierungen zu definieren (mit der C++-Vorlage wird eine ähnliche Sache automatisch vom Compiler durchgeführt).
Eine andere Sache, die ein C++-Compiler automatisch macht, ist die Ableitung der benötigten überladenen Funktion. Das ist in C nicht möglich, also müssen Sie angeben, dass Sie die it-Spezialisierung verwenden. Mit dem folgenden Makro (der C++ <> werden nur durch ersetzt ()):
#define get_minimum(T) get_minimum_##T
Dann sollten Sie es wie folgt aufrufen können:
int main()
{
// Define arr as char* array...
// Do stuff...
int res = get_minimum(int)(arr, 3);
}
Ich habe diesen Code nicht getestet, aber er sollte funktionieren.
Ich mag den Stil des letzten Aufrufs, aber ich habe versucht, dies ohne große Makros zu archivieren.
– fb55
14. Mai 2013 um 9:47 Uhr
@ fb55 Nun, generisch und nicht groß sind in C nicht so kompatibel 🙂
– Jehan
14. Mai 2013 um 16:24 Uhr
Das hat mir an der Antwort von @PaulR gefallen: Das Makro war ziemlich kurz und an anderen Stellen wiederverwendbar 🙂
– fb55
14. Mai 2013 um 16:27 Uhr
@ fb55 Das Problem ist, dass es von einem Parameter zur Kompilierzeit abhängt. Mit seiner Version kann man das nicht verwenden float und die int Version der Funktion in derselben Compile-Unit :/
– Jehan
14. Mai 2013 um 16:29 Uhr
Ich habe meine Antwort jetzt aktualisiert, um zu zeigen, wie mehrere Funktionen für alle erforderlichen Typen in einer Übersetzungseinheit generiert werden.
– PaulR
14. Mai 2013 um 18:00 Uhr
Sie können außer einer Schalteranweisung auch Funktionszeiger (Array von Funktionszeigern) verwenden und das Argument des Schalters als Index an das Array übergeben.
Wenn Sie etwas mehr über “Vorlagen”/”Generika” in C lesen möchten, können Sie diese Frage lesen. Es gibt einige interessante Antworten 🙂
– Jehan
13. Mai 2013 um 13:33 Uhr