खोज…


परिचय

typedef तंत्र अन्य प्रकारों के लिए उपनाम बनाने की अनुमति देता है। यह नए प्रकार का निर्माण नहीं करता है। लोग अक्सर संरचना या संघ प्रकारों को उपनाम देने के लिए, या फ़ंक्शन (या फ़ंक्शन पॉइंटर) प्रकारों के लिए उपनाम बनाने के लिए, कोड की पोर्टेबिलिटी में सुधार करने के लिए typedef का उपयोग करते हैं।

सी मानक में, typedef को सुविधा के लिए 'भंडारण वर्ग' के रूप में वर्गीकृत किया गया है; यह वाक्यात्मक रूप से होता है जहां भंडारण वर्ग जैसे कि static या extern दिखाई दे सकते हैं।

वाक्य - विन्यास

  • typedef मौजूदा_नाम alias_name;

टिप्पणियों


टंकण का नुकसान

typedef सीड बड़े सी कार्यक्रमों में नेमस्पेस के प्रदूषण को जन्म दे सकता है।

टंकण संरचनाओं के नुकसान

इसके अलावा, एक टैग नाम के बिना typedef की संरचनाएं हेडर फ़ाइलों के बीच संबंधों को आदेश देने के लिए अनावश्यक आवश्यकता का एक प्रमुख कारण हैं।

विचार करें:

#ifndef FOO_H
#define FOO_H 1

#define FOO_DEF (0xDEADBABE)

struct bar; /* forward declaration, defined in bar.h*/

struct foo {
    struct bar *bar;
};

#endif

इस तरह की परिभाषा के साथ, typedefs का उपयोग नहीं करते typedefs , FOO_DEF परिभाषा में प्राप्त करने के लिए foo.h को शामिल करना एक संकलन इकाई के लिए संभव है। अगर यह foo स्ट्रक्चर के bar मेंबर को bar.h करने की कोशिश नहीं करता है, तो bar.h फाइल को शामिल करने की कोई जरूरत नहीं होगी।

टाइप्डिफ़ बनाम #define

#define एक सी प्री-प्रोसेसर निर्देश है जिसका उपयोग typedef समान विभिन्न डेटा प्रकारों के लिए उपनामों को परिभाषित करने के लिए भी किया जाता है लेकिन निम्नलिखित अंतरों के साथ:

  • typedef केवल उन प्रकारों को प्रतीकात्मक नाम देने तक सीमित है, जहां #define का उपयोग मूल्यों के लिए उपनाम को परिभाषित करने के लिए किया जा सकता है।

  • typedef व्याख्या कंपाइलर द्वारा की जाती है जबकि #define स्टेटमेंट प्री-प्रोसेसर द्वारा प्रोसेस की जाती है।

  • ध्यान दें कि #define cptr char * बाद cptr a, b; typedef char *cptr; जैसा नहीं करता है typedef char *cptr; इसके बाद cptr a, b;#define साथ, b एक सादा char चर है, लेकिन यह typedef साथ एक सूचक भी है।

संरचनाओं और यूनियनों के लिए टंकण

आप किसी struct को अन्य नाम दे सकते हैं:

typedef struct Person {
    char name[32];
    int age;
} Person;

Person person;

Structs घोषित करने के पारंपरिक तरीके की तुलना में, प्रोग्रामर है की जरूरत नहीं होगी struct हर बार वे कहते हैं कि struct का एक उदाहरण घोषणा करते हैं।

ध्यान दें कि अंतिम अर्धविराम तक Person (जैसा कि struct Person विपरीत) को परिभाषित नहीं किया गया है। इस प्रकार लिंक की गई सूचियों और पेड़ों की संरचनाओं के लिए जो एक ही संरचना प्रकार के लिए एक पॉइंटर को शामिल करने की आवश्यकता है, आपको या तो उपयोग करना होगा:

typedef struct Person {
    char name[32];
    int age;
    struct Person *next;
} Person;

या:

typedef struct Person Person;

struct Person {
    char name[32];
    int age;
    Person *next;
};

एक union प्रकार के लिए एक typedef का उपयोग बहुत समान है।

typedef union Float Float;

union Float
{
    float f;
    char  b[sizeof(float)];
};

इसके समान एक संरचना का उपयोग बाइट्स का विश्लेषण करने के लिए किया जा सकता है जो float मूल्य बनाते हैं।

टंकण की सरल उपयोग

डेटा प्रकार के लिए संक्षिप्त नाम देने के लिए

के बजाय:

long long int foo;
struct mystructure object;

एक का उपयोग कर सकते हैं

/* write once */
typedef long long ll;
typedef struct mystructure mystruct;

/* use whenever needed */
ll foo;
mystruct object;

यह टाइपिंग की मात्रा को कम करता है यदि प्रोग्राम में कई बार टाइप का उपयोग किया जाता है।

पोर्टेबिलिटी में सुधार

डेटा प्रकारों की विशेषताएँ विभिन्न आर्किटेक्चर में भिन्न होती हैं। उदाहरण के लिए, int एक कार्यान्वयन में 2-बाइट प्रकार और दूसरे में 4-बाइट प्रकार हो सकता है। मान लीजिए कि एक प्रोग्राम को सही ढंग से चलाने के लिए 4-बाइट प्रकार का उपयोग करने की आवश्यकता है।

एक क्रियान्वयन में, int का आकार 2 बाइट्स और long 4 बाइट्स का होना चाहिए। दूसरे में, int का आकार 4 बाइट्स है और वह long 8 बाइट्स है। यदि कार्यक्रम दूसरे कार्यान्वयन का उपयोग करते हुए लिखा गया है,

/* program expecting a 4 byte integer */
int foo; /* need to hold 4 bytes to work */
/* some code involving many more ints */

कार्यक्रम को पहले कार्यान्वयन में चलाने के लिए, सभी int घोषणाओं को long बदलना होगा।

/* program now needs long */
long foo; /*need to hold 4 bytes to work */
/* some code involving many more longs - lot to be changed */

इससे बचने के लिए, कोई व्यक्ति typedef उपयोग कर सकता है

/* program expecting a 4 byte integer */
typedef int myint; /* need to declare once - only one line to modify if needed */
myint foo; /* need to hold 4 bytes to work */
/* some code involving many more myints */

फिर, पूरे कार्यक्रम की जांच करने के बजाय, केवल typedef कथन को हर बार बदलना होगा।

C99

<stdint.h> शीर्षक और संबंधित <inttypes.h> हैडर परिभाषित मानक प्रकार नाम (का उपयोग कर typedef विभिन्न आकार के पूर्णांकों, और इन नामों के लिए) अक्सर आधुनिक कोड है कि जरूरतों को तय आकार पूर्णांकों में सबसे अच्छा विकल्प है। उदाहरण के लिए, uint8_t एक अहस्ताक्षरित 8-बिट पूर्णांक प्रकार है; int64_t एक हस्ताक्षरित 64-बिट पूर्णांक प्रकार है। प्रकार uintptr_t एक अहस्ताक्षरित पूर्णांक प्रकार है जो किसी भी सूचक को ऑब्जेक्ट पर रखने के लिए पर्याप्त है। ये प्रकार सैद्धांतिक रूप से वैकल्पिक हैं - लेकिन उनके लिए उपलब्ध नहीं होना दुर्लभ है। uint_least16_t (कम से कम 16 बिट्स के साथ सबसे छोटा अहस्ताक्षरित पूर्णांक प्रकार) और int_fast32_t (कम से कम 32 बिट्स के साथ सबसे तेज़ हस्ताक्षरित पूर्णांक प्रकार) जैसे वेरिएंट हैं। इसके अलावा, intmax_t और uintmax_t कार्यान्वयन द्वारा समर्थित सबसे बड़े पूर्णांक प्रकार हैं। ये प्रकार अनिवार्य हैं।

उपयोग निर्दिष्ट करना या पठनीयता में सुधार करना

यदि डेटा के एक सेट का एक विशेष उद्देश्य है, तो कोई इसे एक सार्थक नाम देने के लिए typedef का उपयोग कर सकता है। इसके अलावा, यदि डेटा की संपत्ति ऐसी बदल जाती है कि आधार प्रकार को बदलना होगा, तो पूरे प्रोग्राम की जांच करने के बजाय केवल typedef कथन को बदलना होगा।

फंक्शन पॉइंटर्स के लिए टाइप्डिफ

हम फ़ंक्शन पॉइंटर्स के उपयोग को सरल बनाने के लिए typedef का उपयोग कर सकते हैं। कल्पना करें कि हमारे कुछ कार्य हैं, सभी में एक ही हस्ताक्षर हैं, जो विभिन्न तरीकों से कुछ का प्रिंट आउट करने के लिए अपने तर्क का उपयोग करते हैं:

#include<stdio.h>

void print_to_n(int n)
{
    for (int i = 1; i <= n; ++i)
        printf("%d\n", i);
}

void print_n(int n)
{
    printf("%d\n, n);
}

अब हम एक typedef का उपयोग करके नामांकित फ़ंक्शन पॉइंटर टाइप प्रिंटर बना सकते हैं:

typedef void (*printer_t)(int);

यह एक प्रकार, नामित बनाता printer_t एक समारोह है कि एक ही ले जाता है के लिए सूचक के लिए int तर्क और रिटर्न कुछ भी नहीं है, जो काम करता है हम ऊपर है के हस्ताक्षर से मेल खाता है। इसका उपयोग करने के लिए हम बनाए गए प्रकार का एक वैरिएबल बनाते हैं और इसे एक प्रश्न में दिए गए कार्यों के लिए एक पॉइंटर असाइन करते हैं:

printer_t p = &print_to_n;
void (*p)(int) = &print_to_n; // This would be required without the type

फिर फ़ंक्शन पॉइंटर चर द्वारा इंगित फ़ंक्शन को कॉल करने के लिए:

p(5);           // Prints 1 2 3 4 5 on separate lines
(*p)(5);        // So does this

इस प्रकार typedef फ़ंक्शन पॉइंटर्स के साथ काम करते समय सरल सिंटैक्स की अनुमति देता है। यह तब और अधिक स्पष्ट हो जाता है जब फ़ंक्शन पॉइंटर्स का उपयोग अधिक जटिल स्थितियों में किया जाता है, जैसे कि कार्यों के लिए तर्क।

यदि आप एक फ़ंक्शन पॉइंटर का उपयोग कर रहे हैं, जो बिना फ़ंक्शन पॉइंटर के पैरामीटर के रूप में फ़ंक्शन पॉइंटर को परिभाषित करता है, तो फ़ंक्शन परिभाषा होगी।

void foo (void (*printer)(int), int y){
    //code
    printer(y);
    //code
}

हालाँकि, यह typedef साथ है:

void foo (printer_t printer, int y){
    //code
    printer(y);
    //code
}

इसी तरह फ़ंक्शन फ़ंक्शन पॉइंटर्स को वापस कर सकते हैं और फिर से, ऐसा करते समय typedef का उपयोग वाक्यविन्यास को सरल बना सकता है।

एक क्लासिक उदाहरण <signal.h> से signal फ़ंक्शन है। इसके लिए घोषणा (सी मानक से) है:

void (*signal(int sig, void (*func)(int)))(int);

यह एक ऐसा फंक्शन है जो दो तर्कों को लेता है - एक int और एक फंक्शन के लिए एक पॉइंटर जो एक आर्ग्युमेंट को एक int रूप में लेता है और कुछ भी नहीं लौटाता है - और जो एक पॉइंटर को दूसरे लॉजिक की तरह काम करने के लिए लौटाता है।

यदि हमने पॉइंटर प्रकार के कार्य के लिए SigCatcher को एक उपनाम के रूप में परिभाषित किया है:

typedef void (*SigCatcher)(int);

तब हम signal() का उपयोग करके घोषणा कर सकते थे:

SigCatcher signal(int sig, SigCatcher func);

कुल मिलाकर, यह समझना आसान है (भले ही सी मानक ने काम करने के लिए एक प्रकार को परिभाषित करने के लिए चुना नहीं था)। signal समारोह दो तर्क, एक लेता है int और एक SigCatcher , और यह एक रिटर्न SigCatcher - जहां एक SigCatcher एक समारोह है कि एक लेता है के लिए सूचक है int तर्क और रिटर्न कुछ भी नहीं।

यद्यपि फ़ंक्शन प्रकारों के लिए सूचक के लिए typedef नामों का उपयोग करना जीवन को आसान बनाता है, यह उन लोगों के लिए भी भ्रम पैदा कर सकता है जो बाद में आपके कोड को बनाए रखेंगे, इसलिए सावधानी और उचित प्रलेखन के साथ उपयोग करें। फ़ंक्शन पॉइंटर्स भी देखें।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow