2010-02-06 23 views
5

क्या निम्न रूपांतरण सुरक्षित है?असुरक्षित रूपांतरण

int b[10][10]; 
char *x; 
int a[]={0,1,2,3,4,5,6,7,8,9}; 

for(int i=0;i<10;i++) 
    for(int j=0;j<10;j++) 
    b[i][j]=a[i]; 

for(x=(char *)&b[0];x<=(char *)&b[9][9];x+=sizeof(a+1)) // Problem lies here! 
    printf("%d\n",*x); 

मुझे नहीं लगता कि for पाश में ऊपर रूपांतरण सुरक्षित है (मुझे लगता है कि यह मंच निर्भर है)। अगर मैं गलत हूं कृपया मुझे सही। मुझे आश्चर्य है क्योंकि कोड जीसीसी में -Wall -pedantic विकल्पों का उपयोग करके संकलित किए जाने पर भी कोई चेतावनी दिए बिना संकलित करता है।

+0

'ए', 'ए + 1' में क्या है? – GManNickG

+0

मुझे लगता है कि यह एक गलत टाइप बी था। हालांकि मैं गलत हो सकता है ... – Pod

+0

@GMan और @Pod: संपादित! –

उत्तर

7

इस पूरी चीज में एक और एक कारण के लिए कानूनी होने का मौका है: 2 डी int सरणी ऑब्जेक्ट को char ऑब्जेक्ट्स की सरणी के रूप में पुन: परिभाषित किया गया है। सामान्य रूप से स्मृति पुनरावृत्ति के कारण अपरिभाषित व्यवहार की ओर जाता है, भाषा विनिर्देश स्पष्ट रूप से किसी भी प्रकार की वस्तुओं के लिए "हस्ताक्षरित/हस्ताक्षरित] चार" पुनरावृत्तियों की सरणी की अनुमति देता है।

हालांकि, एक औपचारिक सुरक्षा समस्या अभी भी वहां है। भाषा गारंटी नहीं देती है कि कोई भी बिट पैटर्न char प्रकार का मान्य मान है। char प्रकार के माध्यम से पुन: परिभाषित स्मृति को पढ़ने का आपका प्रयास सैद्धांतिक रूप से अपरिभाषित व्यवहार का कारण बन सकता है यदि यह char के लिए जाल प्रतिनिधित्व का सामना करता है। यहां सुरक्षित होने के लिए आपको unsigned char प्रकार का उपयोग करना होगा, जो एकमात्र प्रकार है जिसमें कोई जाल प्रस्तुतिकरण नहीं है। बेशक, char को फंसे हुए प्लेटफॉर्म को सुरक्षित रूप से "विदेशी" कहा जा सकता है।

इस बीच, आपके sizeof(a + 1) कोई समझ नहीं आता है। a + 1int * प्रकार की एक अभिव्यक्ति है। इस मामले में अपने x मूल्य को बढ़ाने के लिए आप पॉइंटर आकार का उपयोग क्यों करना चाहते हैं, यह मुझे स्पष्ट नहीं है। आप क्या हासिल करने की कोशिश कर रहे थे?

चेतावनियों की अनुपस्थिति के रूप में ... मैं संकलक से यहां कोई चेतावनी जारी करने की अपेक्षा नहीं करता। जीसीसी अक्सर टाइप-पनिंग (उर्फ मेमोरी रीइंटरटेक्टेशन) के बारे में चेतावनी देता है, लेकिन char के बाद से दोबारा व्याख्या की अनुमति दी जाती है (जैसा कि मैंने ऊपर बताया है), यहां कोई चेतावनी नहीं है। इसके अलावा, स्पष्ट रूप से आमतौर पर किसी भी चेतावनी को दबाने लगते हैं, क्योंकि वे संकलक को यह कहने का एक तरीका हैं कि आप वास्तव में कुछ गलत करना चाहते हैं चाहे यह कितना गलत और/या खतरनाक हो।

+0

@ एंड्रे टी: _ ए + 1 int * type_ की अभिव्यक्ति है और यही वह है जो मैं चाहता हूं। यह एक ऑनलाइन कोडिंग प्रतियोगिता से एक पहेली है। –

+1

@P्रासून: जिस तरह से आपका चक्र दिखता है, मैं उम्मीद करता हूं कि किसी को 'sizeof (int)' का उपयोग करना होगा, जैसे 'sizeof (a [1])' या 'sizeof (* (a + 1)) या ' sizeof (* क) '। 'आकार (ए + 1)' के रूप में, फिर से, मुझे समझ में नहीं आता कि इसका क्या मतलब है। मेरे लिए इसका कोई अर्थ नहीं है। – AnT

+0

मैंने उस विशेष मंच पर आकार (int) और sizeof (int *) को समान मान लिया है। हाँ मुझे लगता है कि आकार (* ए) अधिक सही दिखता है। –

1

किसी भी सूचक प्रकार का char * char * को स्पष्ट रूप से सी भाषा द्वारा अनुमत किया जाता है। तो इसमें से अधिकांश ठीक है।

for(x=(char *)&b[0]; x <= (char *)&b[9][9]; x += sizeof(a+1)) 

पहले भाग x = (char*)&b[0]; सरणी की शुरुआत करने के लिए एक चार सूचक स्थापित करता है ठीक है। परीक्षण भी ठीक है x <= (char *)&b[9][9] सरणी के अंदर एक्स अंक के रूप में तब तक सही होगा।

x += sizeof(a+1) iffy हिस्सा है। अधिकांश 32 बिट सीपीयू आर्किटेक्चर आकार (int *) पर होता है जो आकार (int) के समान होता है, इसलिए यह कोड शायद काम, लेकिन केवल दुर्घटना से होगा।

मुझे यकीन है कि x += sizeof(a[0]) या x += sizeof(b[0]) था, लेकिन कोड वास्तव में क्या किया गया था, किसी ने भी बग को देखा नहीं।

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