2010-05-30 15 views
5

ठीक है मैं अपने सी में एक struct ++ प्रोग्राम है जो इस तरह है:सी ++ अहस्ताक्षरित चार और पूर्णांक बग युक्त struct

struct thestruct 
{ 
unsigned char var1; 
unsigned char var2; 
unsigned char var3[2]; 
unsigned char var4; 
unsigned char var5[8]; 
int var6; 
unsigned char var7[4]; 
}; 

जब मैं इस struct का उपयोग, 3 यादृच्छिक बाइट्स "var6" से पहले जोड़े जाएं, अगर मैं "var5" को हटा देता हूं, यह अभी भी "var6" से पहले है, इसलिए मुझे पता है कि यह हमेशा "var6" से पहले है।

लेकिन अगर मैं "var6" को हटा देता हूं तो 3 अतिरिक्त बाइट चले जाते हैं।

यदि मैं केवल इसमें एक int के साथ एक संरचना का उपयोग करता हूं, तो कोई अतिरिक्त बाइट नहीं है।

तो हस्ताक्षर किए गए चार और int के बीच एक संघर्ष होने लगते हैं, मैं इसे कैसे ठीक कर सकता हूं?

उत्तर

6

संकलक शायद उसके डिफ़ॉल्ट संरेखण विकल्प है, जहां आकार के सदस्यों एक्स एक स्मृति सीमा में समान रूप से विभाजित पर गठबंधन कर रहे हैं उपयोग कर रहा है x

अपने संकलक पर निर्भर करता है, तो आप इस व्यवहार एक #pragma directive का उपयोग कर उदाहरण के लिए प्रभावित कर सकते हैं,:

#pragma pack(1) 

विज़ुअल सी में डिफ़ॉल्ट संरेखण बंद हो जाएगा ++:

मूल्य निर्दिष्ट करता है, बाइट में पैकिंग के लिए इस्तेमाल किया जाना चाहिए। n के लिए डिफ़ॉल्ट मान 8. मान्य मान 1, 2, 4, 8, और 16. एक सदस्य का संरेखण सीमा पर होगा जो या तो n या एकाधिक आकार के एकाधिक सदस्य, जो भी छोटा हो।

ध्यान दें कि कम-स्तर के CPU प्रदर्शन कारणों के लिए, आमतौर पर आपके डेटा सदस्यों को संरेखित करने का प्रयास करना सबसे अच्छा होता है ताकि वे एक गठबंधन सीमा पर आ सकें। कुछ सीपीयू आर्किटेक्चर को संरेखण की आवश्यकता होती है, जबकि अन्य (जैसे इंटेल x86) प्रदर्शन में कमी (कभी-कभी काफी महत्वपूर्ण) के साथ गलत संरेखण को सहन करते हैं।

+0

धन्यवाद जो आपको काम करता है – powerfear

4

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

5

आपकी डेटा संरचना aligned है ताकि आपका int शब्द सीमाओं पर पड़ जाए, जो आपके लक्ष्य के लिए 32 या 64 बिट हो सकते हैं।
तुम इतनी तरह अपने struct पुनर्निर्माण कर सकते हैं ताकि यह नहीं होगा:

struct thestruct 
{ 
int var6; 
unsigned char var1; 
unsigned char var2; 
unsigned char var3[2]; 
unsigned char var4; 
unsigned char var5[8]; 
unsigned char var7[4]; 
}; 
+0

संरचना को पुनर्गठित करने पर अच्छी कॉल, संकलक-निर्भर पैकिंग pragmas/विशेषताओं का उपयोग करने से काफी बेहतर है। –

+0

हालांकि यह अभी भी कार्यान्वयन परिभाषित है। –

0

आपके पास बाइट संरेखण समस्या है। कंपाइलर बाइट्स को संरेखित करने के लिए पैडिंग जोड़ रहा है। this विकिपीडिया लेख देखें।

0

data structure alignment पर पढ़ें। अनिवार्य रूप से, कंपाइलर और संकलन विकल्पों के आधार पर, आपको विभिन्न शक्तियों के संरेखण मिलेगा-2।

यह बचने के लिए, मल्टी-बाइट आइटम (पूर्णांक या संकेत) को स्थानांतरित आइटम एकल-बाइट (हस्ताक्षरित या अहस्ताक्षरित चार) से पहले - हालांकि यह अभी भी अपने अंतिम आइटम के बाद वहाँ हो सकता है।

0

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

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