मैंने कई कार्यक्रमों को देखा है जिसमें नीचे की तरह संरचनाएं हैं
typedef struct
{
int i;
char k;
} elem;
elem user;
इसकी इतनी बार आवश्यकता क्यों है? कोई विशेष कारण या लागू क्षेत्र?
struct * ptrअंदर की रेखा त्रुटि का कारण बन जाएगी
मैंने कई कार्यक्रमों को देखा है जिसमें नीचे की तरह संरचनाएं हैं
typedef struct
{
int i;
char k;
} elem;
elem user;
इसकी इतनी बार आवश्यकता क्यों है? कोई विशेष कारण या लागू क्षेत्र?
struct * ptrअंदर की रेखा त्रुटि का कारण बन जाएगी
जवाबों:
जैसा कि ग्रेग हेवगिल ने कहा, टाइपडिफ का मतलब है अब आपको structसभी जगह लिखना नहीं होगा। यह न केवल कीस्ट्रोक्स को बचाता है, बल्कि यह कोड क्लीनर भी बना सकता है क्योंकि यह एक स्मिगन को अधिक अमूर्तता प्रदान करता है।
सामान की तरह
typedef struct {
int x, y;
} Point;
Point point_new(int x, int y)
{
Point a;
a.x = x;
a.y = y;
return a;
}
क्लीनर बन जाता है, जब आपको "स्ट्रक्चर" कीवर्ड को पूरे स्थान पर देखने की आवश्यकता नहीं होती है, तो यह अधिक लगता है जैसे कि वास्तव में आपकी भाषा में "प्वाइंट" नामक एक प्रकार है। जो, मेरे बाद typedefका मामला है।
यह भी ध्यान दें कि जब आपका उदाहरण (और मेरा) नामकरण struct स्वयं छोड़ दिया गया था, वास्तव में इसका नामकरण तब भी उपयोगी होता है जब आप एक अपारदर्शी प्रकार प्रदान करना चाहते हैं। फिर आपके पास हेडर में इस तरह का कोड होगा, उदाहरण के लिए:
typedef struct Point Point;
Point * point_new(int x, int y);
और फिर structकार्यान्वयन फ़ाइल में परिभाषा प्रदान करें :
struct Point
{
int x, y;
};
Point * point_new(int x, int y)
{
Point *p;
if((p = malloc(sizeof *p)) != NULL)
{
p->x = x;
p->y = y;
}
return p;
}
इस बाद के मामले में, आप पॉइंट को मूल्य से वापस नहीं कर सकते, क्योंकि इसकी परिभाषा हेडर फ़ाइल के उपयोगकर्ताओं से छिपी हुई है। यह उदाहरण के लिए जीटीके + में व्यापक रूप से उपयोग की जाने वाली तकनीक है ।
अद्यतन यह भी ध्यान रखें अत्यधिक माना सी परियोजनाओं जहां के इस प्रयोग देखते हैं कि typedefछिपाने के लिए structएक बुरा विचार माना जाता है, लिनक्स कर्नेल शायद सबसे प्रसिद्ध ऐसी परियोजना है। लाइनस के गुस्से वाले शब्दों के लिए लिनक्स कर्नेल कोडिंगसेल दस्तावेज़ के अध्याय 5 को देखें । :) मेरा कहना है कि सवाल में "चाहिए" पत्थर में सेट नहीं है, सब के बाद।
यह आश्चर्यजनक है कि कितने लोगों को यह गलत लगता है। कृपया C में टाइपफ़ीड संरचना न करें, यह अनावश्यक रूप से वैश्विक नामस्थान को प्रदूषित करता है जो आमतौर पर बड़े कार्यक्रमों में पहले से ही बहुत प्रदूषित है।
इसके अलावा, बिना किसी टैग नाम के टाइप किएडिफैड स्ट्रक्चर्स हेडर फाइलों के बीच रिश्तों को आदेश देने के लिए अनावश्यक आवश्यकता का एक प्रमुख कारण है।
विचार करें:
#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
इस तरह की परिभाषा के साथ, टाइपडिफ्स का उपयोग नहीं करना, यह एक संकलन इकाई के लिए foo.h को FOO_DEFपरिभाषा में शामिल करने के लिए संभव है । यदि यह fooसंरचना के 'बार' के सदस्य को हटाने का प्रयास नहीं करता है, तो "bar.h" फ़ाइल को शामिल करने की कोई आवश्यकता नहीं होगी।
इसके अलावा, चूंकि टैग नामों और सदस्य नामों के बीच नामस्थान भिन्न हैं, इसलिए बहुत पठनीय कोड लिखना संभव है जैसे:
struct foo *foo;
printf("foo->bar = %p", foo->bar);
चूंकि नाम स्थान अलग-अलग हैं, इसलिए उनके संरचनात्मक टैग नाम के साथ संयोग नामकरण चर में कोई संघर्ष नहीं है।
अगर मुझे आपका कोड बनाए रखना है, तो मैं आपके टाइपफीड को हटा दूंगा।
typedef struct X { ... } X। इस तरह आप Xपरिभाषा उपलब्ध होने के बाद कहीं भी संरचना को संबोधित करने के लिए संक्षिप्त रूप का उपयोग कर सकते हैं , लेकिन struct Xवांछित होने पर भी आगे-घोषणा और उपयोग कर सकते हैं।
दान सक्स के एक पुराने लेख से ( http://www.ddj.com/cpp/184403396?pgno=3 ):
नामकरण संरचनाओं के लिए सी भाषा के नियम थोड़े विलक्षण हैं, लेकिन वे बहुत हानिरहित हैं। हालाँकि, जब C ++ में कक्षाएं बढ़ाई जाती हैं, तो वही नियम बग के लिए क्रॉल करने के लिए थोड़ी दरारें खोलते हैं।
C में, नाम दिखाई दे रहा है
struct s { ... };एक टैग है। एक टैग नाम एक प्रकार का नाम नहीं है। उपरोक्त परिभाषा को देखते हुए, घोषणाएँ जैसे
s x; /* error in C */ s *p; /* error in C */सी। में त्रुटियाँ हैं। आप उन्हें इस रूप में अवश्य लिखें
struct s x; /* OK */ struct s *p; /* OK */यूनियनों और गणनाओं के नाम भी प्रकारों के बजाय टैग हैं।
सी में, टैग अन्य सभी नामों (कार्यों, प्रकारों, चर, और गणना स्थिरांक) से अलग हैं। सी संकलक एक प्रतीक तालिका में टैग बनाए रखते हैं जो वैचारिक रूप से है यदि भौतिक रूप से उस तालिका से अलग नहीं है जो अन्य सभी नामों को रखती है। इस प्रकार, एक सी प्रोग्राम के लिए एक टैग और एक अन्य नाम एक ही दायरे में समान वर्तनी के साथ होना संभव है। उदाहरण के लिए,
struct s s;एक वैध घोषणा है जो प्रकार की संरचना एस के चर को घोषित करता है। यह अच्छा अभ्यास नहीं हो सकता है, लेकिन सी संकलक को इसे स्वीकार करना होगा। मैंने कभी इस बात के लिए तर्क नहीं देखा कि सी को इस तरह से क्यों बनाया गया। मैंने हमेशा सोचा है कि यह एक गलती थी, लेकिन यह है।
कई प्रोग्रामर (आपके सहित वास्तव में) प्रकार के नामों के रूप में संरचना के नामों के बारे में सोचना पसंद करते हैं, इसलिए वे टाइप टाइप का उपयोग करके टैग के लिए एक उपनाम को परिभाषित करते हैं। उदाहरण के लिए, परिभाषित करना
struct s { ... }; typedef struct s S;जैसा कि आप संरचना एस के स्थान पर एस का उपयोग करते हैं
S x; S *p;एक प्रोग्राम S को एक प्रकार और एक चर (या फ़ंक्शन या एन्यूमरेशन स्थिर) दोनों के नाम के रूप में उपयोग नहीं कर सकता है।
S S; // errorयह अच्छा है।
एक संरचना, संघ, या enum परिभाषा में टैग नाम वैकल्पिक है। कई प्रोग्रामर टाइप परिभाषा में संरचना की परिभाषा को मोड़ते हैं और टैग के साथ पूरी तरह से फैलाते हैं, जैसे:
typedef struct { ... } S;
लिंक किए गए लेख में इस बात की भी चर्चा है कि कैसे C ++ के व्यवहार की आवश्यकता नहीं होने के typedefकारण सूक्ष्म नाम छिपाने की समस्या हो सकती है। इन समस्याओं को रोकने के लिए, यह typedefC ++ में आपकी कक्षाओं और संरचनाओं के लिए एक अच्छा विचार है, भले ही, पहली नज़र में यह अनावश्यक प्रतीत हो। सी ++ में, typedefनाम छिपाने के साथ एक त्रुटि हो जाती है जो संकलक संभावित समस्याओं के छिपे हुए स्रोत के बजाय आपको बताती है।
int stat(const char *restrict path, struct stat *restrict buf)फ़ंक्शन के साथ (POSIX या Unix) प्रोग्राम में है। वहाँ आप statसाधारण नाम अंतरिक्ष struct statमें और टैग नाम अंतरिक्ष में एक समारोह है।
एक का प्रयोग typedefसे बचा जाता है लिखने के लिए होने structहर बार जब आप उस प्रकार के एक चर घोषित:
struct elem
{
int i;
char k;
};
elem user; // compile error!
struct elem user; // this is correct
typedefसामान्य रूप से आईएनजी संरचनाओं को बदनाम करने का कारण नहीं है । आप भी कर सकते हैं typedef struct foo foo;। बेशक structकीवर्ड की आवश्यकता अधिक नहीं है, जो एक उपयोगी संकेत हो सकता है कि जिस प्रकार का उपनाम हम देखते हैं वह संरचना के लिए एक उपनाम है लेकिन यह सामान्य रूप से खराब नहीं है। एक ऐसे मामले पर भी विचार करें जहां परिणामी प्रकार के उपनाम की पहचान typedefयह इंगित करती है कि यह संरचना के लिए एक उपनाम है, fe typedef struct foo foo_struct;:।
इस समस्या से हमेशा टाइप किए गए एनफॉम और स्ट्रक्चर्स के लिए एक और अच्छा कारण:
enum EnumDef
{
FIRST_ITEM,
SECOND_ITEM
};
struct StructDef
{
enum EnuumDef MyEnum;
unsigned int MyVar;
} MyStruct;
संरचना में EnumDef में टाइपो (Enu u mDef) को नोटिस करें? यह त्रुटि (या चेतावनी) के बिना संकलित है और (सी मानक की शाब्दिक व्याख्या के आधार पर) सही है। समस्या यह है कि मैंने अपनी संरचना के भीतर एक नई (खाली) गणना परिभाषा बनाई है। मैं पिछले परिभाषा EnumDef का उपयोग करके (जैसा कि इरादा था) नहीं हूं।
एक टाइपडीएफ के साथ इसी प्रकार के टाइपो में एक अज्ञात प्रकार का उपयोग करने के लिए एक कंपाइलर त्रुटियां होती हैं:
typedef
{
FIRST_ITEM,
SECOND_ITEM
} EnumDef;
typedef struct
{
EnuumDef MyEnum; /* compiler error (unknown type) */
unsigned int MyVar;
} StructDef;
StrructDef MyStruct; /* compiler error (unknown type) */
मैं हमेशा टाइप किए गए ढांचे और गणनाओं की वकालत करूंगा।
न केवल कुछ टाइपिंग को बचाने के लिए (कोई सज़ा नहीं;)), लेकिन क्योंकि यह सुरक्षित है।
enumएक प्रकार के रूप में उपयोग करने के लिए हतोत्साहित किया जाता है, क्योंकि कई कंपाइलर 'गलत' का उपयोग करते समय अजीब चेतावनी देते हैं। उदाहरण के लिए, enum0 से इनिशियलाइज़ करना एक 'पूर्णांक स्थिरांक को enum' चेतावनी में नहीं दे सकता है। फॉरवर्ड-घोषणा करना enumभी अनुमति नहीं है। इसके बजाय int(या unsigned int) का उपयोग करना चाहिए ।
लिनक्स कर्नेल कोडिंग स्टाइल चैप्टर 5 बड़े पेशेवरों और विपक्षों (अधिकतर कॉन्स) को उपयोग करने की सुविधा देता है typedef।
कृपया "vps_t" जैसी चीजों का उपयोग न करें।
यह संरचनाओं और बिंदुओं के लिए टाइपडिफ का उपयोग करने के लिए एक गलती है। जब आप ए
vps_t a;स्रोत में, इसका क्या मतलब है?
इसके विपरीत यदि यह कहे
struct virtual_container *a;आप वास्तव में बता सकते हैं कि "ए" क्या है।
बहुत से लोग सोचते हैं कि टाइपडेफ "पठनीयता में मदद करते हैं"। ऐसा नहीं। वे केवल इसके लिए उपयोगी हैं:
(ए) पूरी तरह से अपारदर्शी वस्तुएं (जहां टाइपडिफ सक्रिय रूप से उस वस्तु को छिपाने के लिए उपयोग किया जाता है)।
उदाहरण: "pte_t" आदि अपारदर्शी वस्तुएं जिन्हें आप केवल उचित सहायक कार्यों का उपयोग करके एक्सेस कर सकते हैं।
ध्यान दें! अस्पष्टता और "अभिगम कार्य" अपने आप में अच्छे नहीं हैं। हमारे पास उनके लिए pte_t आदि जैसी चीज़ों का कारण यह है कि वास्तव में वहाँ शून्य पूरी तरह से सुलभ जानकारी है।
(b) पूर्णांक प्रकार साफ़ करें, जहाँ अमूर्तता भ्रम से बचने में मदद करती है चाहे वह "int" हो या "long"।
u8 / u16 / u32 पूरी तरह से ठीक प्रकार के हैं, हालांकि वे यहां से बेहतर (डी) श्रेणी में आते हैं।
ध्यान दें! फिर - इसके लिए एक कारण होने की आवश्यकता है । अगर कुछ "लंबे समय से अटूट है", तो ऐसा करने का कोई कारण नहीं है
typedef unsigned long myflags_t;लेकिन अगर कोई स्पष्ट कारण है कि कुछ परिस्थितियों में यह "अहस्ताक्षरित int" हो सकता है और अन्य विन्यासों के तहत "अहस्ताक्षरित लंबा" हो सकता है, तो हर तरह से आगे बढ़ें और एक typedef का उपयोग करें।
(c) जब आप विरल का उपयोग वस्तुतः टाइप-जाँच के लिए एक नया प्रकार बनाने के लिए करते हैं।
(d) नए प्रकार जो कुछ असाधारण परिस्थितियों में, मानक C99 प्रकारों के समान हैं।
हालाँकि यह आंखों और मस्तिष्क को 'uint32_t' जैसे मानक प्रकारों का आदी होने में केवल कुछ समय लगेगा, कुछ लोगों को वैसे भी उनके उपयोग पर आपत्ति है।
इसलिए, लिनक्स-विशिष्ट 'u8 / u16 / u32 / u64' प्रकार और उनके हस्ताक्षरित समकक्ष जो मानक प्रकारों के समान हैं - की अनुमति है - हालांकि वे आपके स्वयं के नए कोड में अनिवार्य नहीं हैं।
मौजूदा कोड को संपादित करते समय जो पहले से ही एक या दूसरे प्रकार के सेट का उपयोग करता है, आपको उस कोड में मौजूदा विकल्पों के अनुरूप होना चाहिए।
(e) उपयोगकर्ताप में उपयोग के लिए सुरक्षित प्रकार।
कुछ संरचनाओं में जो उपयोक्ता के लिए दृश्यमान हैं, हमें C99 प्रकारों की आवश्यकता नहीं हो सकती है और ऊपर 'u32' फॉर्म का उपयोग नहीं किया जा सकता है। इस प्रकार, हम सभी संरचनाओं में __u32 और इसी तरह के प्रकारों का उपयोग करते हैं जो उपयोगकर्ताओं के साथ साझा किए जाते हैं।
हो सकता है कि कुछ अन्य मामले भी हों, लेकिन नियम तब तक होना चाहिए जब तक कि आप उन नियमों में से एक का स्पष्ट रूप से मिलान न कर सकें, जब तक कि वे किसी प्रकार का उपयोग न करें।
सामान्य तौर पर, एक पॉइंटर, या एक संरचना जिसमें ऐसे तत्व होते हैं, जिन्हें उचित रूप से सीधे एक्सेस किया जा सकता है, उन्हें कभी भी टाइपडिफ नहीं होना चाहिए ।
यह पता चला है कि पेशेवरों और विपक्ष हैं। सूचना का एक उपयोगी स्रोत सेमिनल बुक "एक्सपर्ट सी प्रोग्रामिंग" ( अध्याय 3 ) है। संक्षेप में, C में आपके कई नामस्थान हैं: टैग, प्रकार, सदस्य नाम और पहचानकर्ता । typedefएक प्रकार के लिए एक उपनाम का परिचय देता है और इसे टैग नेमस्पेस में ढूँढता है। अर्थात्,
typedef struct Tag{
...members...
}Type;
दो चीजों को परिभाषित करता है। टैग नेमस्पेस में एक टैग और टाइप नेमस्पेस में एक टाइप। तो आप दोनों Type myTypeऔर कर सकते हैं struct Tag myTagType। घोषणाएँ जैसे कि struct Type myTypeया Tag myTagTypeअवैध हैं। इसके अलावा, इस तरह से एक घोषणा में:
typedef Type *Type_ptr;
हम अपने प्रकार के लिए एक पॉइंटर को परिभाषित करते हैं। इसलिए अगर हम घोषणा करते हैं:
Type_ptr var1, var2;
struct Tag *myTagType1, myTagType2;
उसके बाद var1, var2और myTagType1टाइप करने के लिए संकेत कर रहे हैं , लेकिन myTagType2नहीं।
उपर्युक्त पुस्तक में, यह उल्लेख किया गया है कि टाइप किए गए संरचनाएं बहुत उपयोगी नहीं हैं क्योंकि यह प्रोग्रामर को केवल शब्द संरचना लिखने से बचाता है। हालांकि, मुझे कई अन्य प्रोग्रामर की तरह आपत्ति है। यद्यपि यह कभी-कभी कुछ नामों को बाधित करने के लिए बदल जाता है (यही कारण है कि यह कर्नेल की तरह बड़े कोड आधारों में उचित नहीं है) जब आप सी में बहुरूपता को लागू करना चाहते हैं तो यह विवरण के लिए यहां बहुत मदद करता है । उदाहरण:
typedef struct MyWriter_t{
MyPipe super;
MyQueue relative;
uint32_t flags;
...
}MyWriter;
तुम कर सकते हो:
void my_writer_func(MyPipe *s)
{
MyWriter *self = (MyWriter *) s;
uint32_t myFlags = self->flags;
...
}
इसलिए आप कास्टिंग के माध्यम से बाहरी flagsसंरचना ( MyPipe) द्वारा एक बाहरी सदस्य ( ) तक पहुंच सकते हैं । मेरे लिए यह (struct MyWriter_ *) s;इस तरह की कार्यक्षमता करने के लिए हर बार की तुलना में पूरे प्रकार कास्ट करने के लिए कम भ्रमित नहीं है । इन मामलों में संक्षिप्त संदर्भ एक बड़ी बात है, खासकर यदि आप अपने कोड में तकनीक को भारी रूप से नियोजित करते हैं।
अंत में, typedefएड प्रकार के साथ अंतिम पहलू मैक्रोज़ के विपरीत, उन्हें विस्तारित करने में असमर्थता है। यदि उदाहरण के लिए, आपके पास:
#define X char[10] or
typedef char Y[10]
फिर आप घोषणा कर सकते हैं
unsigned X x; but not
unsigned Y y;
हम वास्तव में इस संरचना के लिए परवाह नहीं करते हैं क्योंकि यह भंडारण विनिर्देश ( volatileऔर const) पर लागू नहीं होता है ।
MyPipe *s; MyWriter *self = (MyWriter *) s;और आपने अभी-अभी सख्त अलियासिंग को तोड़ा है।
typedef struct Tag{ ...members... }Type; " दो चीजों को परिभाषित करता है "काफी समझ में नहीं आता है।" अगर टाइपडिफ टैग को परिभाषित करता है तो यहां 'टाइप' भी टैग होना चाहिए। सच्चाई परिभाषा 2 टैग और 1 प्रकार परिभाषित करता है (या 2 प्रकार और 1 टैग यकीन नहीं।) है: struct Tag, Tagऔर Type। struct Tagनिश्चित रूप से एक प्रकार है। Tagएक टैग है। लेकिन भ्रम यह है कि क्या Typeएक टैग या एक प्रकार है
मुझे नहीं लगता कि टाइपडेफ के साथ आगे की घोषणाएं भी संभव हैं। जब निर्भरता (के बारे में पता चलता है) द्विदिश है, तो संरचना, एनम और संघ का उपयोग घोषणाओं को आगे बढ़ाने की अनुमति देता है।
शैली: C ++ में टाइपडिफ का उपयोग काफी मायने रखता है। कई और / या चर मापदंडों की आवश्यकता वाले टेम्पलेट्स से निपटने के दौरान यह लगभग आवश्यक हो सकता है। टाइम्डिफ नामकरण को सीधा रखने में मदद करता है।
C प्रोग्रामिंग लैंग्वेज में ऐसा नहीं है। टंकण का उपयोग अक्सर डेटा संरचना के उपयोग को बाधित करने के लिए बिना किसी उद्देश्य के होता है। चूंकि केवल {स्ट्रक्चर (6), एनम (4), यूनियन (5)} कीस्ट्रोक्स की संख्या का उपयोग डेटा प्रकार घोषित करने के लिए किया जाता है, संरचना के अलियासिंग के लिए लगभग कोई उपयोग नहीं है। क्या वह डेटा एक संघ या एक संरचना है? सीधे-सीधे गैर-टाइप किए गए घोषणा का उपयोग करने से आपको तुरंत पता चल जाता है कि यह किस प्रकार का है।
ध्यान दें कि कैसे लिनक्स को इस अलियासिंग बकवास टाइपिडेफ के सख्त परिहार के साथ लिखा गया है। परिणाम एक न्यूनतम और साफ शैली है।
structहर जगह दोहरा नहीं होगा ... टाइप्डिफ नए प्रकार बनाते हैं। तुम क्या इस्तेमाल करते हो? प्रकार। हम इसकी परवाह नहीं करते हैं कि यह एक संरचना, मिलन या एनम है, इसलिए हम इसे टाइप करते हैं।
FILE?
आइए मूल बातों से शुरू करें और अपने तरीके से काम करें।
यहाँ संरचना परिभाषा का एक उदाहरण है:
struct point
{
int x, y;
};
यहां नाम pointवैकल्पिक है।
एक संरचना को इसकी परिभाषा के दौरान या उसके बाद घोषित किया जा सकता है।
परिभाषा के दौरान घोषणा
struct point
{
int x, y;
} first_point, second_point;
परिभाषा के बाद घोषणा
struct point
{
int x, y;
};
struct point first_point, second_point;
अब, ऊपर के अंतिम मामले को ध्यान से देखें; struct pointयदि आप अपने कोड में बाद में उस प्रकार का निर्माण करने का निर्णय लेते हैं, तो आपको उस प्रकार की संरचनाएं घोषित करने के लिए लिखना होगा।
दर्ज करें typedef। यदि आप एक ही खाका का उपयोग करके अपने कार्यक्रम में बाद के समय में नई संरचना (संरचना एक कस्टम डेटा-प्रकार) बनाने का इरादा रखते हैं, तो typedefइसकी परिभाषा के दौरान उपयोग करना एक अच्छा विचार हो सकता है क्योंकि आप कुछ टाइपिंग को आगे बढ़ने से बचा सकते हैं।
typedef struct point
{
int x, y;
} Points;
Points first_point, second_point;
कुछ भी आपको अपने कस्टम प्रकार के नाम के अंत में _t प्रत्यय का उपयोग करने से रोकता है लेकिन POSIX मानक मानक लाइब्रेरी प्रकार नामों को निरूपित करने के लिए प्रत्यय _t के उपयोग को सुरक्षित रखता है।
जो नाम आप (वैकल्पिक रूप से) देते हैं वह संरचना टैग नाम कहलाता है और, जैसा कि नोट किया गया है, अपने आप में एक प्रकार नहीं है। टाइप करने के लिए स्ट्रक्चर प्रीफिक्स की जरूरत होती है।
GTK + एक तरफ, मुझे यकीन नहीं है कि tagname का उपयोग कुछ भी किया जाता है जैसे कि आमतौर पर टाइप टाइप के रूप में संरचना प्रकार के लिए, इसलिए C ++ में जो मान्यता प्राप्त है और आप संरचना कीवर्ड को छोड़ सकते हैं और टाइप नाम के रूप में भी tagname का उपयोग कर सकते हैं:
struct MyStruct
{
int i;
};
// The following is legal in C++:
MyStruct obj;
obj.i = 7;
डेटा प्रकारों के लिए अधिक सार्थक समानार्थी शब्द बनाने की अनुमति देकर प्रोग्राम के अर्थ और प्रलेखन में ए> टाइपडीएफ एड्स । इसके अलावा, वे पोर्टेबिलिटी समस्याओं (K & R, pg147, C prog lang) के खिलाफ एक प्रोग्राम को पैरामीटर बनाने में मदद करते हैं।
B> एक संरचना एक प्रकार को परिभाषित करती है । संरचनाएं एकल इकाई के रूप में हैंडलिंग की सुविधा (K & R, pg127, Cg lang।) के लिए var के संग्रह के सुविधाजनक समूहन की अनुमति देती हैं।
C> टाइपडिफिंग एक संरचना ए में ऊपर बताई गई है।
D> मेरे लिए, संरचनाएँ कस्टम प्रकार या कंटेनर या संग्रह या नाम स्थान या जटिल प्रकार हैं, जबकि एक टाइपडेफ़ केवल अधिक उपनाम बनाने का एक साधन है।
C99 टाइपफेड में टर्न आउट आवश्यक है। यह पुराना है, लेकिन बहुत सारे उपकरण (ala HackRank) अपने शुद्ध C कार्यान्वयन के रूप में c99 का उपयोग करते हैं। और वहां टाइप्डिफ़ की आवश्यकता है।
मैं यह नहीं कह रहा हूं कि उन्हें बदलना चाहिए (शायद दो सी विकल्प हैं) यदि आवश्यकता बदल गई, तो हम में से जो साइट पर साक्षात्कार के लिए अध्ययन कर रहे हैं वे एसओएल होंगे।
typedefकी आवश्यकता है।" क्या मतलब?
Cनहीं C++। में Ctypedefs हैं 'आवश्यक' (और सबसे अधिक संभावना हमेशा हो जाएगा)। 'आवश्यक' के रूप में, आप एक चर घोषित करने में सक्षम नहीं होंगे Point varName;और टाइप struct Point;बिना पर्यायवाची हो सकते हैं typedef struct Point Point;।
'C' प्रोग्रामिंग लैंग्वेज में 'typeedef' कीवर्ड का इस्तेमाल किसी ऑब्जेक्ट (स्ट्रक्चर, एरे, फंक्शन..नम टाइप) के लिए एक नया नाम घोषित करने के लिए किया जाता है। उदाहरण के लिए, मैं 'संरचना-एस' का उपयोग करूंगा। 'सी' में हम अक्सर 'मेन' फंक्शन के बाहर 'स्ट्रक्चर' घोषित करते हैं। उदाहरण के लिए:
struct complex{ int real_part, img_part }COMPLEX;
main(){
struct KOMPLEKS number; // number type is now a struct type
number.real_part = 3;
number.img_part = -1;
printf("Number: %d.%d i \n",number.real_part, number.img_part);
}
हर बार जब मैं एक संरचनात्मक प्रकार का उपयोग करने का निर्णय लेता हूं, तो मुझे इस कीवर्ड की संरचना 'कुछ' नाम की आवश्यकता होगी। तो हमारा कोड होगा:
typedef struct complex{int real_part, img_part; }COMPLEX;
//now COMPLEX is the new name for this structure and if I want to use it without
// a keyword like in the first example 'struct complex number'.
main(){
COMPLEX number; // number is now the same type as in the first example
number.real_part = 1;
number.img)part = 5;
printf("%d %d \n", number.real_part, number.img_part);
}
यदि आपके पास कुछ स्थानीय वस्तु (संरचना, सरणी, मूल्यवान) है जो आपके पूरे कार्यक्रम में उपयोग की जाएगी, तो आप इसे केवल एक नाम लिख सकते हैं 'टाइप्डिफ'।
सभी में, सी भाषा में, स्ट्रक्चर / यूनियन / एनम सी भाषा प्रीप्रोसेसर द्वारा संसाधित मैक्रो इंस्ट्रक्शन हैं (प्रीप्रोसेसर के साथ गलती न करें जो "#include" और अन्य का इलाज करते हैं)
इसलिए :
struct a
{
int i;
};
struct b
{
struct a;
int i;
int j;
};
संरचना ख कुछ इस तरह से खर्च की जाती है:
struct b
{
struct a
{
int i;
};
int i;
int j;
}
और इसलिए, संकलन समय पर यह स्टैक पर विकसित होता है जैसे कि: बी: इंट एआईआई इंट आई इंट जे
यह भी कि यह आत्मनिर्भर संरचनाएं होने के लिए अलग क्यों है, एक प्रसार लूप में सी प्रीप्रोसेसर राउंड को पूरा नहीं कर सकता है।
टाइपराइफ़ टाइप स्पेसिफ़ायर हैं, इसका मतलब है कि केवल सी कंपाइलर प्रक्रिया है और यह ऐसा कर सकता है जैसे वह कोडांतरक कोड कार्यान्वयन के लिए चाहता है। यह भी प्रकार के बराबर का सदस्य खर्च नहीं करता है जैसे कि préprocessor स्ट्रक्चर्स के साथ करता है, लेकिन अधिक जटिल संदर्भ निर्माण एल्गोरिथ्म का उपयोग करता है, इसलिए निर्माण निम्न है:
typedef struct a A; //anticipated declaration for member declaration
typedef struct a //Implemented declaration
{
A* b; // member declaration
}A;
अनुमति है और पूरी तरह कार्यात्मक है। यह कार्यान्वयन कंपाइलटर प्रकार के रूपांतरण तक पहुंच प्रदान करता है और निष्पादन थ्रेड के प्रारंभिक कार्य को छोड़ देने पर कुछ बगिंग प्रभाव को हटा देता है।
इसका मतलब यह है कि सी टाइलेडिफ्स में अकेला पैटर्न की तुलना में सी ++ वर्ग के पास अधिक है।
structsलिए और typedefएस बुरा पर्याप्त है, लेकिन अपने लेखन के बाकी तो भ्रामक है कि मैं यह मुश्किल यह से किसी भी संदेश प्राप्त करने के लिए लगता है। एक बात मैं कह सकता हूं, हालांकि, यह है कि आपका विचार यह है कि एक गैर- typedefडी structको आगे घोषित नहीं किया जा सकता है या एक अपारदर्शी (पॉइंटर) सदस्य के रूप में उपयोग किया जाता है, पूरी तरह से गलत है। आपके पहले उदाहरण में, struct bतुच्छ रूप से एक struct a *, कोई typedefआवश्यक नहीं हो सकता है। जो कथ्य structकेवल स्थूल-विस्तार के गूंगे टुकड़े हैं, और जो typedefउन्हें क्रांतिकारी नई शक्तियाँ प्रदान करते हैं, वे दर्दनाक रूप से गलत हैं