2011-09-10 9 views
10
typedef struct foo_s { 
    int a; 
} foo; 

typedef struct bar_s { 
    foo; 
    int b; 
} bar; 

अनिवार्य रूप से मैं क्या करना चाहते हैं:क्या मैं सी में एक संरचना का विस्तार कर सकता हूं?

bar b; 
b.a; 

मुझे पता है कि मैं b.foo_name.a अगर मैं बार में foo struct नाम दिया था कर सकता है, लेकिन ईद नहीं पसंद करते हैं।

ऐसा करने का कोई तरीका?

इस प्रश्न को विभिन्न उत्तरों के विभिन्न मिल गए हैं, इसलिए मुझे आवश्यकता की व्याख्या करने दें। कारण मैं ऐसा करना चाहता हूं क्योंकि मेरे पास एक पुस्तकालय है जिसे मुझे अपनी स्थिति में अनुकूलित करने की आवश्यकता है, जिसका अर्थ है कि मैं मूल संरचना अस्वीकरण को संशोधित नहीं कर सकता। इसके अलावा, मुझे बस इतना करना है कि संरचना की शुरुआत में 1 आइटम जोड़ें (शुरुआत क्यों? क्योंकि मेरे पास एक 'ऑब्जेक्ट' संरचना है जो परियोजना में सभी structs का नेतृत्व करती है)। मैं बस आपके जैसा उल्लेख कर सकता हूं जैसे संरचना को एम्बेड कर सकता हूं लेकिन यह वास्तव में कष्टप्रद है क्योंकि सभी संदर्भों को 'variable-> image.location' टाइप करना होगा जो 'छवि' है। एक अरब प्रकार टाइप किया वास्तव में कष्टप्रद है।

+0

कुछ compilers वास्तव में है कि व्यवहार के रूप में की पेशकश एक विस्तार व्यक्तिगत रूप से मुझे लगता है कि यह बहुत अधिक जोखिम प्रदान करता है (घोंसले की संरचना 'छः परतों को गहरा कर रहा है और भूल रहा है कि आपने किन नामों का उपयोग किया है) इसलिए मैं पहले सदस्य' _' - लघु, संगत, रास्ते से बाहर, और बहुत ही असुविधाजनक नहीं । (नाम वास्तव में मानक और/या कंपाइलर द्वारा आरक्षित किया जा सकता है लेकिन मुझे संदेह है कि अगर कोई होता तो कोई इसका इस्तेमाल करेगा।) –

+0

यदि 'छवि' बहुत टाइप करने के लिए परेशान है, तो' img' का उपयोग करें। अपने लिए यह करने के लिए ढूंढें और प्रतिस्थापित करें। चिंता न करें - जो भी आप करना चाहते हैं, आप जीवित रहेंगे। –

+0

@ चचम 15 दोस्त, सी ++ के रूप में सी प्रश्न को टैग करने से बचें। ये दोनों पूरी तरह से अलग भाषाएं हैं। –

उत्तर

19

जाहिर this feature has been added to C11, लेकिन अफसोस मैं हाल ही में पुरानी (> = जीसीसी 4.6.2) के एक सी संकलक करने के लिए पहुँच नहीं है।

typedef struct foo { 
    int a; 
} foo; 

typedef struct bar { 
    struct foo; 
    int b; 
} bar; 

int main() { 
    bar b; 
    b.a = 42; 
    b.b = 99; 
    return 0; 
} 
+1

के अन्य संस्करणों के लिए कोई कामकाज था, ध्यान दें कि यह काम करता है क्योंकि 'बार' के भीतर, 'struct foo' अनामित रूप से उपयोग किया जाता है (यानी एक चर नाम के बिना)। –

7

C में आपके द्वारा किए गए तरीके से संभव नहीं है। लेकिन आप foo सदस्य चर के bar में विरासत की नकल कर सकते हैं।

typedef struct bar_s { 
    foo obj; 
    int b; 
} bar; 

bar b; 
b.obj.a = 10; 
+5

जिसे [composition] (http://en.wikipedia.org/wiki/Composition_over_inheritance) कहा जाता है अगर मुझे गलत नहीं लगता है। – michaelsnowden

1

आप विरासत आज़मा सकते हैं:, यकीन नहीं अगर यह सी में काम करता है

+1

मेरा बुरा, आप सही हैं, मुझे नहीं पता कि मैंने सी ++ टैग क्यों जोड़ा, मेरा मतलब सी था। sry! – chacham15

+4

मुझे यकीन है कि सी –

+0

सर्वश्रेष्ठ उत्तर नहीं है, यहां तक ​​कि यह सी ++ है। – lama12345

2

आप

typedef struct foo_s { 
    int a; 
    } foo; 

typedef struct bar_s { 
foo my_foo; 
int b; 
} bar; 

तो आप क्या कर सकते हैं जाहिर हैं

सी ++ में
struct foo_s 
{ 
    int a; 
}; 

struct bar_s: foo_a 
{ 
    int b; 
}; 

वर्क्स :

bar b; b.my_foo.a = 3; 

अन्यथा, सी में ऐसा करने का कोई तरीका नहीं है क्योंकि sizeof(bar_s) संकलन समय पर हानि है। यह एक अच्छा अभ्यास नहीं है लेकिन आप बार_s के भीतर void * ptr; पॉइंटर बचा सकते हैं, और एक अन्य enum जो ptr प्रकार का वर्णन करता है, और प्रकार के द्वारा कास्ट करता है।

अर्थात्:

typedef enum internalType{ 
    INTERNAL_TYPE_FOO = 0, 
}internalType_t; 

typedef struct bar_s { 
internalType_t ptrType; 
void* ptr; 
int b; 
} bar; 

और उसके बाद:

bar b; foo f; 
b.ptrType = INTERNAL_TYPE_FOO; 
b.ptr = &f; 

और कुछ और कहाँ कोड में:

if (b.ptrType == INTERNAL_TYPE_FOO) { 
    foo* myFooPtr = (foo *)b.ptr; 
} 
+0

प्रश्न ने आपके द्वारा वर्णित रन-टाइम "प्रकार" की इच्छा का कोई उल्लेख नहीं किया है। –

+0

@ क्रिस लुट्ज़ शायद ओवरबोर्ड पर है, लेकिन यह सवाल को संबोधित करता है ... –

+0

@ क्रिस, आप सही हो सकते हैं, लेकिन "bar.a" मुझे एक पायथन कोड की तरह दिखता है (जहां कक्षाओं को रन-टाइम पर बढ़ाया जा सकता है) । तो यह मेरे दिमाग में सबसे पहले आया था ... –

9

आप कर सकते हैं, संकेत का उपयोग कर, क्योंकि एक संरचना करने के लिए एक सूचक वस्तु को अपने पहले सदस्य को इंगित करने की गारंटी है। उदाहरण देखें this article

#include <stdlib.h> 
#include <stdio.h> 

typedef struct foo_s { 
    int a; 
} foo; 

typedef struct bar_s { 
    foo super; 
    int b; 
} bar; 

int fooGetA(foo *x) { 
    return x->a; 
} 

void fooSetA(foo *x, int a) { 
    x->a = a; 
} 

int main() { 
    bar* derived = (bar*) calloc(1, sizeof(bar)); 
    fooSetA((foo*) derived, 5); 
    derived->b = 3; 
    printf("result: %d\n", fooGetA((foo*) derived)); 
    return 0; 
} 
+1

यह तब भी बेहतर होता है जब वे 'शून्य *' पॉइंटर्स लेते हैं और कॉलर-साइड कास्टिंग से बचते हैं। ("बेहतर" के कुछ लोगों के मूल्य मेरे से अलग हो सकते हैं।) –

+1

हां, यह कॉलर के लिए निश्चित रूप से अधिक सुविधाजनक है। मैं यह दिखाना चाहता था कि फू फ़ंक्शंस के लेखक को यह नहीं पता होना चाहिए कि "वास्तविक" संरचना foo से कुछ और है। –

+1

ठीक है, दोनों दृष्टिकोण एक ही समय में सही और गलत हैं। टाइपकास्ट को कम गुणवत्ता वाले क्लाइंट कोड को मजबूर करना पड़ता है। इसे 'शून्य *' का उपयोग करके हल किया जा सकता है, हालांकि टाइप सुरक्षा को समाप्त करता है जो इससे भी बदतर है। फिर भी ये एक अच्छा जवाब और कुछ अच्छे तर्क हैं, विशेष रूप से जौनी की अंतिम टिप्पणी जब यह अवशोषण (विरासत का बिंदु) की बात आती है, फिर भी उपर्युक्त कारकों को ध्यान में रखना आवश्यक है। यहां सी 11 समाधान है: ** http: //modelingwithdata.org/arch/00000113.htm**; मुझे आश्चर्य है कि सी – Powerslave

0

यह आसानी से पूर्वप्रक्रमक के माध्यम से किया जा सकता है:

नाम की एक फ़ाइल base_foo.h बनाएँ:

int foo; 

तो बस इसे शामिल हैं:

typedef struct foo_s { 
    #include "base_foo.h" 
} foo; 

typedef struct bar_s { 
    #include "base_foo.h" 
    int b; 
} bar; 
संबंधित मुद्दे

 संबंधित मुद्दे