2016-12-30 12 views
7

इस स्निपेट में, VLA करने के लिए एक सूचक आसान पहुँच के लिए एक बड़ा लुकअप तालिका करने के लिए प्रयोग किया जाता है:कास्ट "सूचक VLA const करने के लिए" से "const सूचक"

#pragma GCC diagnostic warning "-Wcast-qual" 

char 
lookup(int a, int b, int c, char const *raw, int x, int y, int z) 
{ 
    typedef char const (*DATA_PTR)[a][b][c]; 

    DATA_PTR data = (DATA_PTR)raw; 

    return (*data)[x][y][z]; 
} 

जीसीसी 6.2.0क्लैंग 4.0.0 (ट्रंक)-Wcast-qual सक्षम दोनों के साथ ठीक है, जबकि इस पर चोक करता है।

In function 'lookup': 
warning: cast discards 'const' qualifier from pointer target type [-Wcast-qual] 
    DATA_PTR data = (DATA_PTR)raw; 
       ^

कोड किसी भी तरह से अपेक्षित है।

मेरा अनुमान है जीसीसी और "VLA const सूचक" "स्थिरांक तत्वों के VLA सूचक" एक confuses लेकिन मैं पहुँच रहा हूँ है ...

वहाँ चेतावनी के साथ नगण्य बिना जीसीसी चुप रहो करने के लिए एक तरीका है? क्या यह एक जीसीसी बग है?

EDIT1: वास्तविक कोड पर

विवरण:

struct table { 
    int a; 
    int b; 
    int c; 
    char *raw; 
}; 

char 
lookup2(struct table const *table, int x, int y, int z) 
{ 
    typedef char const(*DATA_PTR)[table->a][table->b][table->c]; 

    DATA_PTR data; 
    data = (DATA_PTR)table->raw; // GCC ok 
    data = (DATA_PTR)(char const *)table->raw; // GCC raises -Wcast-qual 

    return (*data)[x][y][z]; 
} 

EDIT2:

तो वहाँ यह है ... C11 मानक प्रारूप 6.7.3 में कहते हैं/9:

यदि विशिष्ट किसी सरणी प्रकार के आयन में किसी भी प्रकार के क्वालीफायर शामिल होते हैं, तत्व प्रकार इतना योग्य होता है, सरणी प्रकार नहीं।

@hvd उत्तर देखें।

एक हैक -Wcast-qual मौन करने:

DATA_PTR data = (DATA_PTR)(intptr_t)raw; 
+3

"कॉन्स्ट तत्वों के वीएलए के सूचक" और "वीएलए को कॉन्स्ट करने के लिए सूचक" एक ही बात है। एक कॉन्स सरणी कॉन्स तत्वों की एक सरणी है। एक बग की तरह लगता है। – emlai

+0

क्यों पूरी चीज को थोड़ा और अधिक सुरक्षित नहीं बनाते हैं, और 'कच्चे' को 'char const (* raw) [a] [b] [c]' में बनाते हैं? – StoryTeller

+0

@StoryTeller मैंने जोड़ा कि कोड कैसा दिख सकता है लेकिन फिर भी, '-Wcast-qual' अजीब है। – diapir

उत्तर

6

यह सी में एक लंबे समय से मुद्दा है यह वही कारण है कि

int array[2]; 
const int (*ptr)[2] = &array; 

सी में अमान्य है है (लेकिन सी में मान्य होगा ++): यह const -क्वालिफाइड पूर्णांक की एक सरणी के लिए एक सूचक घोषित करता है, जो const-पूर्णांक की योग्य सरणी नहीं है, इसलिए सामान्य नियम कि किसी प्रकार के पॉइंटर को पूर्ण रूप से पीओ में परिवर्तित किया जा सकता है const के लिए इंटर-उस प्रकार का योग्य संस्करण लागू नहीं होता है।

आपके मामले में, आप const char * से (एक सूचक एक const -qualified प्रकार के) char const (*)[a][b][c] है, जो -Wcast-qual के बारे में चेतावनी देने के लिए माना जाता है (एक सूचक एक गैर const -qualified प्रकार के) रूपांतरित करते हैं।

क्लैंग ने सी की इस विशेष विषमता को लागू करने के लिए कभी भी परेशान नहीं किया है, यह सी ++ अर्थशास्त्र के साथ सी कोड का इलाज करता है, जो कहता है कि const तत्वों की एक सरणी स्वयं const है - साथ ही साथ।

आप सामान्यत: struct में सरणी लपेटकर द्वारा उसके चारों ओर काम करने में सक्षम हो जाएगा:

typedef struct { char d[a][b][c]; } const *DATA_PTR; 

लेकिन इस Vlas के लिए एक विकल्प नहीं है। मुझे विश्वास नहीं है कि यहां पर बहु-आयामी सरणी का उपयोग न करने के अलावा, या -Wcast-qual का उपयोग न करने के अलावा कोई उपयुक्त कामकाज नहीं है।

+0

चेतावनियों के साथ फिडलिंग तब होता है ... क्या आप उदाहरणों से अवगत हैं जहां सी (+ क्लैंग की तरह) में सी ++ नियम का उपयोग संभवतः खतरनाक हो सकता है? मानक में इसके लिए कोई कारण नहीं है: _6.7.3.9 यदि किसी सरणी प्रकार के विनिर्देश में किसी भी प्रकार के क्वालीफायर शामिल हैं, तो तत्व प्रकार इतना योग्य है, सरणी प्रकार नहीं ._ – diapir

+1

@diapir सी ++ नियम सुरक्षित है, जहां तक ​​'const'-correctness जाता है और सी के लिए भी प्रस्तावित किया गया है (हालांकि मुझे इसकी स्थिति पता नहीं है)। यदि आप इसका उपयोग करते हैं तो एकमात्र जोखिम अब यह है कि आप गलती से अमान्य/नहीं-अभी-वैध सी कोड लिख सकते हैं जो तब सख्त सी कंपाइलर का उपयोग होने पर त्रुटि का कारण बनता है। – hvd

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