2012-06-27 8 views
5

असल में, मैं जो चाहता हूं वह कुछ प्रकार का संकलन-समय उत्पन्न संस्करण है जो संरचना की सटीक परिभाषा से जुड़ा हुआ है। यदि संरचना की परिभाषा किसी भी तरह से बदलती है (फ़ील्ड जोड़ा गया, स्थानांतरित किया गया, शायद का नाम बदला गया), तो मैं भी उस संस्करण को बदलना चाहता हूं।संरचना परिभाषा का संस्करण आईडी जेनरेट करें?

यह सुनिश्चित करने के लिए कि यह अभी भी संगत है, पहले सेरियलाइज्ड स्ट्रक्चर में पढ़ते समय ऐसा संस्करण निरंतर उपयोगी होगा। विकल्प मैन्युअल रूप से मैन्युअल रूप से निर्दिष्ट निरंतर स्थिरता का ट्रैक रखेगा, जो संभावित रूप से भ्रमित प्रभाव डालता है यदि इसे बढ़ाना भूल जाता है (deserializing कचरा पैदा करता है), और यह भी सवाल उठता है कि वास्तव में इसे बढ़ाने के लिए (विकास और परीक्षण के दौरान, या केवल किसी प्रकार के दौरान रिलीज के)।

यह संरचना परिभाषा पर हैश उत्पन्न करने के लिए बाहरी उपकरण का उपयोग करके हासिल किया जा सकता है, लेकिन मुझे आश्चर्य है कि सी संकलक (और/या शायद इसके प्रीप्रोसेसर) के साथ यह संभव है या नहीं।

यह वास्तव में आत्मनिरीक्षण का कुछ रूप है और इसलिए मुझे संदेह है कि यह एएनएसआई सी में संभव नहीं हो सकता है, लेकिन मैं एक समाधान से खुश हूं जो जीसीसी और क्लैंग के साथ काम करता है।

उत्तर

2

को (अब भी करता है?) एक struct के पहले सदस्यों में से एक के रूप में एक आकार सदस्य, इतना है कि यह struct इसे पारित किया जा रहा था (WNDCLASSEX एक उदाहरण के रूप देखें) का कौन सा संस्करण पता था कि राशि का इस्तेमाल किया Windows API:

struct Foo f; 

f.size = sizeof(struct Foo); 
f.bar = strdup("hi"); 
f.baz = strdup("there"); 

somefunc(&f); 

फिर somefunc पता होगा, size सदस्य है, जो struct से निपटने के संस्करण के आधार पर:

struct Foo 
{ 
    size_t size; 
    char *bar; 
    char *baz; 
    /* Other fields */ 
}; 

और आप कॉल करने से पहले आकार sizeof का उपयोग कर निर्धारित किया है। चूंकि sizeof का मूल्यांकन रन-टाइम की बजाय संकलन समय पर किया जाता है, यह पिछली एबीआई संगतता की अनुमति देता है।

+0

इस के लिए कोई एमएस संदर्भ? – ouah

+0

एक उदाहरण जोड़ा गया –

+0

धन्यवाद। मैंने बस आकार का उपयोग करने के बारे में सोचा, लेकिन निश्चित रूप से उन क्षेत्रों के खिलाफ सुरक्षा नहीं करता है जो स्थानांतरित हो जाते हैं, या अन्य परिचालन जो किसी भी पहले देखे गए आकार में परिणामस्वरूप होते हैं। विंडोज एपीआई के लिए, शायद संशोधनों को केवल फ़ील्ड के जोड़ों में सीमित करने का एक अच्छा विचार है, लेकिन मैं वर्तमान में वास्तव में उस पर जाना नहीं चाहता हूं ... –

2

कुछ भी नहीं है कि यह स्वचालित रूप से करना होगा नहीं है, लेकिन आप कुछ है कि यथोचित मज़बूती से काम करता है का निर्माण कर सकते हैं: आप sizeof और offsetof उपयोग कर सकते हैं, और उन्हें इस तरह से कि जिस क्रम में आप उन्हें गठबंधन अहमियत में गठबंधन। यहाँ एक उदाहरण है:

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

#define COMBINE2(a,b) ((a)*31+(b)*11) 
#define COMBINE3(a,b,c) COMBINE2(COMBINE2(a,b),c) 
#define COMBINE4(a,b,c,d) COMBINE2(COMBINE3(a,b,c),d) 

typedef struct A { 
    int a1; 
    char a2; 
    float a3; 
} A; 

typedef struct B { 
    int b1; 
    char b2; 
    double b3; 
} B; 

typedef struct C { 
    char c2; 
    int c1; 
    float c3; 
} C; 

typedef struct D { 
    int d1; 
    char d2; 
    float d3; 
    int forgotten[2]; 
} D; 

int main(void) { 
    size_t aSign = COMBINE4(sizeof(A), offsetof(A,a1), offsetof(A,a2), offsetof(A,a3)); 
    size_t bSign = COMBINE4(sizeof(B), offsetof(B,b1), offsetof(B,b2), offsetof(B,b3)); 
    size_t cSign = COMBINE4(sizeof(C), offsetof(C,c1), offsetof(C,c2), offsetof(C,c3)); 
    size_t dSign = COMBINE4(sizeof(D), offsetof(D,d1), offsetof(D,d2), offsetof(D,d3)); 
    printf("%ld %ld %ld %ld", aSign, bSign, cSign, dSign); 
    return 0; 
} 

इस कोड prints

358944 478108 399864 597272 

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

+0

आह, मैं 'ऑफ़सेट' के बारे में भूल गया। मुझे लगता है कि यह एएनएसआई सी के साथ सबसे नज़दीकी चीज है? –

+0

@ जुलिएन हां, मुझे लगता है कि आप कम से कम एएनएसआई सी के भीतर इन दोनों को संयोजित करने से कहीं ज्यादा बेहतर नहीं कर सकते हैं। आप एक बेहतर 'कॉम्बिने' बना सकते हैं, हालांकि: मेरा एक त्वरित और गंदा काम जैसा दिखता है, हालांकि मैं कुछ ऐसा उपयोग करता हूं कि विभिन्न संरचनाओं को हैशिंग के लिए उत्पादन कोड में। – dasblinkenlight

+0

@ जुलिएन यदि आपके पास कोई प्रतिबंध नहीं है कि फ़ंक्शन को संकलित समय पर गणना की जानी चाहिए, तो आप संरचनाओं के फ़ील्ड के नामों का प्रतिनिधित्व करने वाले तारों पर हैश की गणना करके संभावित रूप से नामकरण के खिलाफ सुरक्षा कर सकते हैं (आपको '#' प्रीप्रोसेसर स्ट्रिंगफिकेशन ऑपरेटर का उपयोग करना होगा उसके लिए)। – dasblinkenlight