विभिन्न कंपाइलरों पर शून्य में रूपांतरण


9

मैं विभिन्न कंपाइलरों के माध्यम से निम्नलिखित कोड चला रहा हूं:

int main()
{
    float **a;
    void **b;
    b = a;
}

मैं जो इकट्ठा करने में सक्षम था, void **वह जेनेरिक पॉइंटर नहीं है , जिसका अर्थ है कि दूसरे पॉइंटर से किसी भी रूपांतरण को कम से कम चेतावनी नहीं देनी चाहिए। हालाँकि, यहाँ मेरे परिणाम हैं (सभी विंडोज पर किए गए हैं):

  • gcc - जैसा कि अपेक्षित है, एक चेतावनी फेंकता है।
  • g ++ - एक त्रुटि फेंकता है, जैसा कि अपेक्षित था (यह C ++ की सही अनुमेय टाइपिंग के कारण है?)
  • MSVC (cl.exe) - निर्दिष्ट / दीवार के साथ भी, कोई चेतावनी नहीं फेंकता है।

मेरा सवाल है: क्या मैं पूरी चीज़ के बारे में कुछ याद कर रहा हूं और क्या कोई विशेष कारण है कि एमएसवीसी चेतावनी नहीं देता है? MSVC से चेतावनी देते समय उत्पादन करता है । void **float **

नोट की एक और बात: यदि मैं a = bस्पष्ट रूपांतरण से प्रतिस्थापित करता हूं a = (void **)b, तो कोई भी संकलक चेतावनी नहीं देता है। मैंने सोचा कि यह एक अमान्य कलाकार होना चाहिए, इसलिए कोई चेतावनी क्यों नहीं होगी?

मैं यह प्रश्न पूछ रहा हूं क्योंकि मैं CUDA सीखना शुरू कर रहा था और आधिकारिक प्रोग्रामिंग गाइड ( https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device.ememory ) निम्नलिखित कोड पाया जा सकता है:

// Allocate vectors in device memory
float* d_A;
cudaMalloc(&d_A, size);

के प्रकार के पहले तर्क के रूप में, के void **लिए एक अंतर्निहित रूपांतरण करना चाहिए । इसी तरह का कोड सभी प्रलेखन में पाया जा सकता है। क्या यह सिर्फ NVIDIA के अंत पर मैला काम है या मैं फिर से, कुछ याद कर रहा हूं? चूंकि MSVC का उपयोग करता है, कोड चेतावनी के बिना संकलित करता है।&d_AcudaMallocvoid **nvcc


3
पोस्ट किए गए 3 लाइव से त्रुटियां: godbolt.org/z/GQWMNo
रिचर्ड क्रिटेन

3
MSVC के साथ मेरे लिए कोड त्रुटियां। आपके द्वारा कौन सा संस्करण उपयोग किया जा रहा है? लेकिन हां, void**जेनेरिक पॉइंटर नहीं है। केवल void*है
नेथनऑलिवर

त्वरित उत्तर के लिए धन्यवाद! जाहिरा तौर पर x64 के लिए 19.24.28315? मैंने वास्तव में MSVC का उपयोग पहले नहीं किया है।
CaptainProton42

2
(void**)एक स्पष्ट सी शैली कास्ट है। यह संकलक से कहता है कि आप जो कर रहे हैं उस पर बारीकी से गौर न करें और आप पर भरोसा करें। यह प्रकार की सुरक्षा प्रणाली का एक स्पष्ट ओवरराइड है और मूल रूप से किसी भी प्रकार के रूपांतरण को स्वीकार करने के लिए कंपाइलर्स की आवश्यकता होती है। सी स्टाइल कास्ट से बचा जाना चाहिए, वे वैसे भी शक्तिशाली हैं। C ++ कास्ट्स का उपयोग करें जैसे static_castकि अगर आप कुछ ऐसा करने की कोशिश कर रहे हैं जो शिकायत नहीं करेगा।
फ्रांस्वा एंड्रीक्स

@RichardCritten गलत भाषा - कोई त्रुटि नहीं godbolt.org/z/RmFpgN C ++ cuda के लिए आमतौर पर स्पष्ट कास्ट की आवश्यकता होती है।
P__J__

जवाबों:


4

क्या मुझे पूरी चीज़ के बारे में कुछ याद आ रहा है और क्या कोई विशेष कारण है कि MSVC चेतावनी का उत्पादन नहीं करता है? MSVC शून्य चेतावनी से फ्लोट में परिवर्तित करते समय एक चेतावनी उत्पन्न करता है **

कलाकारों के बिना यह असाइनमेंट एक बाधा उल्लंघन है, इसलिए एक मानक अनुरूप संकलक एक चेतावनी या त्रुटि प्रिंट करेगा। हालांकि, MSVC पूरी तरह से C कार्यान्वयन का अनुपालन नहीं कर रहा है।

नोट की एक और बात: यदि मैं a = b को स्पष्ट रूपांतरण a = (शून्य **) b से प्रतिस्थापित करता हूं, तो कोई भी संकलक चेतावनी नहीं देता है। मुझे लगा कि यह एक अमान्य कलाकार होना चाहिए, इसलिए कोई चेतावनी क्यों नहीं होगी?

कुछ स्थितियों में एक कलाकार के माध्यम से सूचक रूपांतरण की अनुमति है। C मानक 6.3.2.3p7 खंड में निम्नलिखित कहता है:

एक वस्तु प्रकार के लिए एक सूचक को एक अलग वस्तु प्रकार के लिए एक सूचक में परिवर्तित किया जा सकता है। यदि परिणामी सूचक को संदर्भित प्रकार के लिए सही ढंग से संरेखित नहीं किया गया है, तो व्यवहार अपरिभाषित है। अन्यथा, जब वापस फिर से परिवर्तित किया जाता है, तो परिणाम मूल सूचक के बराबर तुलना करेगा। जब किसी ऑब्जेक्ट के पॉइंटर को पॉइंटर से कैरेक्टर टाइप में बदल दिया जाता है, तो परिणाम ऑब्जेक्ट के निम्नतम बाइट को इंगित करता है। परिणाम की क्रमिक वृद्धि, ऑब्जेक्ट के आकार तक, ऑब्जेक्ट के शेष बाइट्स को संकेत देता है।

तो आप पॉइंटर प्रकारों के बीच कनवर्ट कर सकते हैं बशर्ते कि कोई संरेखण मुद्दे न हों और आप केवल वापस कनवर्ट करें (जब तक कि लक्ष्य नहीं है char *)।

float* d_A;
cudaMalloc(&d_A, size);

...

क्या यह सिर्फ NVIDIA के अंत पर मैला काम है या मैं फिर से, कुछ याद कर रहा हूं?

संभवतया, यह फ़ंक्शन दिए गए पॉइंटर को dereferencing और कुछ आवंटित मेमोरी का पता लिख ​​रहा है। इसका मतलब होगा कि यह एक float *तरह से लिखने की कोशिश कर रहा है जैसे कि यह एक था void *। यह / से a के विशिष्ट रूपांतरण के समान नहीं है void *। कड़ाई से बोलने पर यह अपरिभाषित व्यवहार की तरह दिखता है, हालांकि यह "काम करता है" क्योंकि आधुनिक x86 प्रोसेसर (जब वास्तविक मोड में नहीं है) सभी सूचक प्रकारों के लिए समान प्रतिनिधित्व का उपयोग करते हैं।


@dbush बहुत जानकारीपूर्ण, धन्यवाद! मुझे लगता है कि अगर यह काम करता है तो यह क्यों काम करता है। फिर भी, अधिकांश संकलक एक चेतावनी या त्रुटि भी नहीं फेंकेंगे क्योंकि &d_Aआवश्यक प्रकार नहीं है?
CaptainProton42

3
सावधान रहें कि आप इस व्याख्या, वहाँ हो सकता है और टेम्पलेट चालें कर रहे हैं कर सकते हैं के बीच यदि आप संकलन CUDA के साथ एक सी ++ संकलक
talonmies
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.