Syntax und Beispielverwendung von _Generic in C11

Lesezeit: 4 Minuten

Benutzeravatar von ApprenticeHacker
LehrlingHacker

Ich habe gehört, dass C11 Generika hinzugefügt hat. Ich habe ein bisschen gegoogelt, mir einige Artikel angesehen und verstanden, dass es ein neues Schlüsselwort gibt ( _Generic ) und alles. Aber ich kann nicht alles fassen.

Ist es so etwas wie die Generics in C# oder Templates in C++? Kann mir jemand kurz die C11-Definition von Generika, ihre Syntax und ein einfaches Anwendungsbeispiel erläutern?

  • Sie können eine lesen oder herunterladen Entwurf des C11-Standards (PDF-Version). Es hat ein Beispiel in Abschnitt 6.5.1.1.

    – pmg

    21. März 2012 um 12:17 Uhr


  • So etwas wie “Generika” gibt es in C++ nicht.

    – Griwes

    21. März 2012 um 12:29 Uhr

  • @Griwes bitte schön. noch mehr Spitzfindigkeiten?

    – Hackerlehrling

    21. März 2012 um 12:31 Uhr

Benutzeravatar von Alex Gray
Alex Grau

Das beste Beispiel, das ich gesehen habe inspirierte das folgende (ausführbare) Beispiel, das alle möglichen verrückten Möglichkeiten für eine durchgeknallte Selbstbeobachtung freisetzt …

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>

#define typename(x) _Generic((x),        /* Get the name of a type */             \
                                                                                  \
        _Bool: "_Bool",                  unsigned char: "unsigned char",          \
         char: "char",                     signed char: "signed char",            \
    short int: "short int",         unsigned short int: "unsigned short int",     \
          int: "int",                     unsigned int: "unsigned int",           \
     long int: "long int",           unsigned long int: "unsigned long int",      \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
        float: "float",                         double: "double",                 \
  long double: "long double",                   char *: "pointer to char",        \
       void *: "pointer to void",                int *: "pointer to int",         \
      default: "other")

#define fmt "%20s is '%s'\n"
int main() {

  size_t s; ptrdiff_t p; intmax_t i; int ai[3] = {0}; return printf( fmt fmt fmt fmt fmt fmt fmt fmt,

     "size_t", typename(s),               "ptrdiff_t", typename(p),     
   "intmax_t", typename(i),      "character constant", typename('0'),
 "0x7FFFFFFF", typename(0x7FFFFFFF),     "0xFFFFFFFF", typename(0xFFFFFFFF),
"0x7FFFFFFFU", typename(0x7FFFFFFFU),  "array of int", typename(ai));
}
                 ╔═══════════════╗ 
═════════════════╣ Amazeballs... ╠═════════════════════════════════════
                 ╚═══════════════╝ 
            size_t is 'unsigned long int'
         ptrdiff_t is 'long int'
          intmax_t is 'long int'
character constant is 'int'
        0x7FFFFFFF is 'int'
        0xFFFFFFFF is 'unsigned int'
       0x7FFFFFFFU is 'unsigned int'
      array of int is 'other'

  • Beeindruckend. welchen Compiler verwendest du? Auf meinem Rechner (Linux, GCC 4.9+) wird der neueste Typ als “Zeiger auf Int” angezeigt: Array von Int ist “Zeiger auf Int”.

    – Benutzer1284631

    26. März 2015 um 15:52 Uhr

  • > Apple LLVM Version 6.1.0 (clang-602.0.45) (basierend auf LLVM 3.6.0svn)

    – Alex Gray

    27. März 2015 um 2:06 Uhr

  • Das ist nett, aber man kann auf diese Weise nie alle Arten abdecken … trotzdem +1 für “Amazeballs” …

    – einpoklum

    18. November 2015 um 10:09 Uhr

  • Eigentlich, @einpoklum, können Sie auf diese Weise alle nicht zusammengesetzten Typen abdecken … es gibt fünf ganzzahlige Typen und ihre vorzeichenlosen Gegenstücke und 3 Gleitkommatypen und ihre komplexen Gegenstücke für insgesamt 16 Grundtypen. Wenn Sie Speicherklassen (normal, const, volatileund volatile const), das Ihnen 64 verschiedene Variationen gibt. Umständlich, aber nicht unmöglich. Zeiger auf jeden dieser Typen verdoppeln diese Zahl, und Zeiger auf Zeiger erhöhen sie weiter … aber das ergibt insgesamt 192 Variationen … ugh! Aber immer noch nicht unmöglich.

    – SGeorgiaden

    26. Februar 2021 um 18:02 Uhr

  • @SGeorgiades: Aber Sie möchten, dass typename() auch für zusammengesetzte Typen funktioniert.

    – einpoklum

    26. Februar 2021 um 18:43 Uhr

Benutzeravatar von unwind
entspannen

Dies ist eine ziemlich gute Einführung. Hier ist die Übersicht:

Die generische Auswahl wird mit einem neuen Schlüsselwort implementiert: _Generic. Die Syntax ähnelt einer einfachen switch-Anweisung für Typen:_Generic( 'a', char: 1, int: 2, long: 3, default: 0)
ergibt 2 (Zeichenkonstanten sind in C Ints).

Im Grunde funktioniert es wie eine Art switchwobei die Bezeichnungen Typnamen sind, die gegen den Typ des ersten Ausdrucks (die 'a' Oben). Das Ergebnis wird das Ergebnis der Auswertung der _Generic().

  • Mir ist gerade aufgefallen, dass ich auf die gleiche Seite wie du verlinkt habe. Kein Wunder, aber es ist wirklich die einzige gute Stelle für Informationen zu diesem Zeug, seltsamerweise …

    – Alex Grau

    25. Juni 2013 um 6:23 Uhr

Ich verwende clion 1.2.4 und clion unterstützt c11 jetzt nicht, also verwende ich den folgenden Code in c99 anstelle von _Generic

#include <stdio.h>

int main(int argc, char **argv) {
    char *s;
    if (__builtin_types_compatible_p(__typeof__(s), long)) {
        puts("long");
    } else if (__builtin_types_compatible_p(__typeof__(s), char*)) {
        puts("str");
    }
    return (0);
};

  • Wie kommt es, dass „Hier ist, was ich anstelle von _Generic verwende“ 8 Upvotes auf eine Frage hat, in der nach einem Beispiel für die Verwendung von _Generic gefragt wird

    – Michael Mrozek

    5. Januar 2019 um 6:59 Uhr

  • @MichaelMrozek – Diese Antwort bietet einen alternativen Ansatz, der nicht zuletzt veranschaulichend für die ist Konzept gefragt. Ein Merkmal eines alternativen Ansatzes zu irgendetwas ist, dass es immer wieder neue und einzigartige Perspektiven bietet die Sache, nach der gefragt wird. Lehrer verwenden diese Technik die ganze Zeit. Wenn Sie an einer Stelle stehen und auf etwas starren und es dennoch nicht verstehen, gehen Sie herum und betrachten Sie es aus einer anderen Perspektive. Dies liefert immer neue Informationen. Das, ob beabsichtigt oder nicht, ist eine Sache, die diese Antwort bietet. (+1 dafür)

    – ryker

    15. Mai 2019 um 12:38 Uhr


  • Das ist GNU C, nicht C99

    – osven

    31. Mai 2020 um 16:48 Uhr

1419520cookie-checkSyntax und Beispielverwendung von _Generic in C11

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy