2012-03-21 25 views
49

में _Generic का सिंटेक्स और नमूना उपयोग मैंने सी 11 जोड़ा जेनिक्स सुना। मैंने कुछ गड़बड़ कर लिया है, कुछ लेखों को देखा है, समझ गया है कि एक नया कीवर्ड है (_Generic) और सब कुछ। लेकिन मैं इसे समझने के लिए प्रतीत नहीं कर सकता।सी 11

क्या यह सी #+ में सी # या टेम्पलेट्स में जेनेरिक की तरह कुछ है? क्या कोई मुझे जेनेरिक, सी सिंटैक्स और सरल नमूना उपयोग उदाहरण की सी 11 परिभाषा का संक्षिप्त विवरण दे सकता है?

+3

के बजाय c99 में निम्न कोड का उपयोग करता हूं, आप पढ़ सकते हैं या एक [सी 11 मानक का मसौदा] डाउनलोड करें (http://www.open-std.org/JTC1/sc22/wg14/www/docs/n1570.pdf) (पीडीएफ संस्करण)। इसका खंड 6.5.1.1 में एक उदाहरण है। – pmg

+3

सी ++ में "जेनेरिक" जैसी कोई चीज़ नहीं है। – Griwes

+6

@ यहां आप जा रहे हैं। कोई और नाइटपिकिंग? – ApprenticeHacker

उत्तर

34

This एक बहुत अच्छा परिचय है। यहां अवलोकन है:

जेनेरिक चयन एक नए कीवर्ड के साथ लागू किया गया है: _Generic। वाक्यविन्यास प्रकारों के लिए सरल स्विच स्टेटमेंट के समान है: _Generic('a', char: 1, int: 2, long: 3, default: 0) 2 का मूल्यांकन करता है (वर्ण स्थिरांक सी में इंक हैं)।

मूल रूप से यह switch का एक प्रकार है, जहां लेबल प्रकार के नाम जो पहली अभिव्यक्ति के प्रकार के खिलाफ जांच की जाती है (ऊपर 'a') कर रहे हैं की तरह काम करता है। परिणाम _Generic() का मूल्यांकन करने का परिणाम बन गया है।

+1

बस एहसास हुआ कि मैंने आपके जैसा ही पृष्ठ से लिंक किया है .. कोई आश्चर्य नहीं, हालांकि .. यह वास्तव में इस सामान पर किसी भी जानकारी के लिए एकमात्र अच्छी जगह है, अजीब ... –

53

The best example I have seen निम्नलिखित (runnable) उदाहरण है, जो फटा-आउट आत्मनिरीक्षण फ्रीकी संभावनाओं के सभी प्रकार बातें बताता है ...

#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' 
+1

वाह। आप किस कंपाइलर का उपयोग करते हैं? मेरी मशीन (लिनक्स, जीसीसी 4.9+) पर, नवीनतम प्रकार को "पॉइंटर टू इंट" के रूप में दिखाया गया है: int की सरणी 'int to pointer' – user1284631

+0

> ऐप्पल एलएलवीएम संस्करण 6.1.0 (क्लैंग -602.0.45) (आधारित एलएलवीएम 3.6.0 एसवीएन) –

+3

यह साफ है, लेकिन आप इस तरह से सभी प्रकारों को कभी भी कवर नहीं कर सकते ... वैसे भी, "अमेज़बॉल" के लिए +1 ... – einpoklum

3

मैं Clion 1.2.4 का उपयोग प्रेरित है, और क्लियन अब सी 11 का समर्थन नहीं करता है, इसलिए मैं _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); 
};