2012-06-21 14 views
6

मैं एक सी संरचना का आकार 16 बाइट्स (16 बी/32 बी/48 बी/..) के एकाधिक होना चाहता हूं। इससे कोई फ़र्क नहीं पड़ता कि यह किस आकार में आता है, इसे केवल 16 बी के एकाधिक होने की आवश्यकता है। मैं ऐसा करने के लिए कंपाइलर को कैसे लागू कर सकता हूं? धन्यवाद।सी संरचना आकार संरेखण

+4

कंपाइलर क्या है? – Joe

+1

आपका शीर्षक शब्द संरेखण का उपयोग करता है हालांकि आपके प्रश्न का शरीर संरचना के आकार के बारे में बात करता है। क्या वास्तव में आप पूरा करना चाहते हैं? और मैं भी उत्सुक हूं कि क्यों। –

+0

और यहां एक मौजूदा आलेख है जो किसी विशेष आकार में पैड के लिए यूनियन का उपयोग करके समाधान प्रदान करता है। हालांकि उस समाधान के लिए संरचना [आकार का आकार] (http://stackoverflow.com/questions/8705665/force- विशिष्ट- संरचना- आकार-in-c) के आकार को जानने की आवश्यकता है, हालांकि आपको उपयोग करने की आवश्यकता होगी चार सरणी के लिए एक आकार की गणना (आकार (संरचना इसे)/16 + 1) * 16 निरंतर संख्या के बजाय 16। –

उत्तर

5

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

हालांकि यदि आप इस विधि पर जोर देते हैं तो संरचना के स्मृति आवंटन करना होगा और अगले 16 बाइट आकार तक स्मृति आवंटन को मजबूर करना होगा।

तो यदि आपके पास इस तरह की संरचना थी।

struct _simpleStruct { 
    int iValueA; 
    int iValueB; 
}; 

फिर आप निम्न की तरह कुछ कर सकते हैं।

{ 
    struct _simpleStruct *pStruct = 0; 
    pStruct = malloc ((sizeof(*pStruct)/16 + 1)*16); 
    // use the pStruct for whatever 
    free(pStruct); 
} 

यह क्या होगा, आकार के अगले 16 बाइट आकार तक आकार को धक्का देना है, जहां तक ​​आप चिंतित थे। हालांकि स्मृति आवंटक क्या करता है जो आपको वास्तव में उस ब्लॉक को देने के लिए हो सकता है या नहीं। स्मृति का ब्लॉक वास्तव में आपके अनुरोध से बड़ा हो सकता है।

यदि आप इसके साथ कुछ विशेष करने जा रहे हैं, उदाहरण के लिए कहें कि आप इस संरचना को एक फ़ाइल में लिखने जा रहे हैं और आप ब्लॉक आकार को जानना चाहते हैं तो आपको उसी गणना का उपयोग करना होगा malloc() संरचना के आकार की गणना करने के लिए sizeof() ऑपरेटर का उपयोग करने के बजाय।

तो अगली बात एक मैक्रो का उपयोग करके अपना स्वयं का आकार() ऑपरेटर लिखना होगा।

#define SIZEOF16(x) ((sizeof(x)/16 + 1) * 16) 

जहां तक ​​मुझे पता है कि एक पॉइंटर से आवंटित ब्लॉक के आकार को खींचने के लिए कोई भरोसेमंद तरीका नहीं है। आम तौर पर एक पॉइंटर में स्मृति आवंटन ब्लॉक होता है जिसका उपयोग स्मृति ढेर प्रबंधन कार्यों द्वारा किया जाता है जिसमें आवंटित ब्लॉक आकार जैसी विभिन्न मेमोरी प्रबंधन जानकारी होगी जो वास्तव में अनुरोधित मात्रा की स्मृति से बड़ी हो सकती है। हालांकि इस ब्लॉक के प्रारूप और जहां यह वास्तविक स्मृति पते के सापेक्ष स्थित है, वह सी संकलक के रन टाइम पर निर्भर करेगा।

+0

आपको [malloc() 'के वापसी मूल्य को सी में नहीं डालना चाहिए (http://stackoverflow.com/a/605858/28169)। – unwind

5

यह पूरी तरह से कंपाइलर और अन्य उपकरणों पर निर्भर करता है क्योंकि संरेखण को आईएसओ सी मानक में गहराई से निर्दिष्ट नहीं किया गया है (यह निर्दिष्ट करता है कि संरेखण कंपेलरों के आदेश पर संरेखण हो सकता है लेकिन इसे लागू करने के तरीके के बारे में विस्तार से नहीं जाता है)।

आपको अपने कंपाइलर टूलचेन के लिए कार्यान्वयन-विशिष्ट सामग्री को देखने की आवश्यकता होगी। यह #pragma pack (या align या कुछ अन्य चीज़) प्रदान कर सकता है जिसे आप अपनी संरचना परिभाषा में जोड़ सकते हैं।

यह इसे एक भाषा विस्तार के रूप में भी प्रदान कर सकता है।

struct mystruct { int val[7]; } __attribute__ ((aligned (16))); 
11

माइक्रोसॉफ्ट विजुअल C के लिए ++:

#pragma pack(push, 16) 

struct _some_struct 
{ 
    ... 
} 

#pragma pack(pop) 

जीसीसी के लिए:

struct _some_struct { ... } __attribute__ ((aligned (16))); 

उदाहरण उदाहरण के लिए, जीसीसी आप एक परिभाषा, जिनमें से एक को नियंत्रित करता है संरेखण में विशेषताएं जोड़ने के लिए अनुमति देता:

#include <stdio.h> 

struct test_t { 
    int x; 
    int y; 
} __attribute__((aligned(16))); 

int main() 
{ 
    printf("%lu\n", sizeof(struct test_t)); 
    return 0; 
} 

संकलित gcc -o main main.c के साथ 16 आउटपुट होगा। वही अन्य कंपाइलरों के लिए जाता है।

+1

जीसीसी __attribute__ गठबंधन के लिए, क्या यह वास्तव में संरचना आकार को 16 बी के बहुमत के लिए मजबूर कर रहा है? या क्या यह गारंटी देता है कि संरचना का प्रारंभ पता 16 बी के साथ गठबंधन किया गया है? –

+1

प्रारंभिक पता और संरचना के आकार दोनों को 16 बी के साथ गठबंधन किया जाएगा। यह संरचनाओं की सरणी के तत्वों के सही संरेखण को आश्वस्त करने के लिए किया जाता है। – Romeo

+0

यह सच नहीं है। __attribute (गठबंधन (x))) मैक्रो एक एक्स-बाइट सीमा पर संरचना आवंटित करता है और संरचना के आकार के साथ कुछ भी नहीं है http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc /Variable-Attributes.html –

3

आप शायद, एक डबल struct कर सकता गद्दी जोड़ सकते हैं कि एक दूसरे से एक में अपने वास्तविक struct लपेटकर:

struct payload_padded a; 

a.p.d = 43.3; 
बेशक

:

struct payload { 
    int a; /*Your actual fields. */ 
    float b; 
    char c; 
    double d; 
}; 

struct payload_padded { 
    struct payload p; 
    char padding[16 * ((sizeof (struct payload) + 15)/16)]; 
}; 

तो फिर तुम गद्देदार struct के साथ काम कर सकते हैं , आप इस तथ्य का उपयोग कर सकते हैं कि संरचना का पहला सदस्य संरचना से शुरू होने वाले 0 बाइट्स से शुरू होता है, और पॉइंटर को struct payload_padded पर इलाज करता है जैसे कि यह struct payload (क्योंकि यह है) के पॉइंटर है:

float d_plus_2(const struct payload *p) 
{ 
    return p->d + 2; 
} 

/* ... */ 

struct payload_padded b; 
const double dp2 = d_plus_2((struct payload *) &b);