বিভিন্ন সংকলকগুলিতে ** অকার্যকর রূপান্তর


9

আমি বিভিন্ন সংকলকের মাধ্যমে নিম্নলিখিত কোডটি চালাচ্ছি:

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

আমি যা সংগ্রহ করতে পারব থেকে, void **হয় না একটি জেনেরিক পয়েন্টার যার মানে অন্য পয়েন্টার থেকে কোন রূপান্তর কম্পাইল করা উচিত নয় বা অন্তত একটি সতর্কবার্তা নিক্ষেপ করা। তবে, এখানে আমার ফলাফলগুলি (উইন্ডোতে সমস্ত সম্পন্ন হয়েছে):

  • জিসিসি - প্রত্যাশার মতো একটি সতর্কতা নিক্ষেপ করে।
  • g ++ - প্রত্যাশার মতো ত্রুটি ছুঁড়েছে (এটি সি ++ এর কম অনুমতিপ্রাপ্ত টাইপিংয়ের কারণে হয়েছে কি?)
  • এমএসভিসি (cl.exe) - এমনকি / ওয়াল নির্দিষ্ট করেও কোনও সতর্কতা দেয় না।

আমার প্রশ্নটি: আমি কি পুরো জিনিসটি সম্পর্কে কিছু মিস করছি এবং এমএসভিসি সতর্কতা উত্থাপন করার কোনও নির্দিষ্ট কারণ নেই? MSVC করে যখন রূপান্তর একটি সতর্কবার্তা উত্পাদন থেকে void ** থেকে float **

নোটের আরেকটি বিষয়: আমি যদি a = bস্বচ্ছ রূপান্তরটি দিয়ে প্রতিস্থাপন করি a = (void **)bতবে সংকলকগুলির মধ্যে কেউ সতর্কতা ছুঁড়ে না ফেলে। আমি ভেবেছিলাম এটি একটি অবৈধ castালাই হওয়া উচিত, তবে কেন কোনও সতর্কতা থাকবে না?

আমি এই প্রশ্নটি জিজ্ঞাসা করার কারণটি হ'ল আমি CUDA এবং অফিসিয়াল প্রোগ্রামিং গাইড ( https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory ) শিখতে শুরু করেছি was নিম্নলিখিত কোডটি পাওয়া যাবে:

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

যা একটি অন্তর্নিহিত রূপান্তর সম্পাদন করা উচিত void **জন্য &d_A, প্রথম আর্গুমেন্ট হিসাবে এর cudaMallocধরনের হয় void **। ডকুমেন্টেশন জুড়ে একই কোড পাওয়া যাবে। এটি কি এনভিআইডিআইএর শেষ দিকে ঝিমঝিম কাজ নাকি আমি আবার কিছু হারিয়ে যাচ্ছি? যেহেতু nvccএমএসভিসি ব্যবহার করে, কোড সতর্কতা ছাড়াই সংকলন করে।


3
পোস্ট করা 3 লাইভ থেকে ত্রুটিগুলি: Godbolt.org/z/GQWMNo
রিচার্ড ক্রিটেন

3
আমার জন্য এমএসভিসি কোড ত্রুটি। আপনি কোন সংস্করণ ব্যবহার করছেন? তবে হ্যাঁ, void**জেনেরিক পয়েন্টার নয়। শুধু void*হয়।
নাথান অলিভার

দ্রুত উত্তরের জন্য ধন্যবাদ! X64 আপাতদৃষ্টিতে 19.24.28315? আমি সত্যিই এর আগে এমএসভিসি ব্যবহার করি নি।
ক্যাপ্টেনপ্রোটন 42

2
(void**)একটি স্পষ্টত সি স্টাইলের castালাই। এটি সংকলককে বলে যে আপনি কী করছেন তা ঘনিষ্ঠভাবে না দেখে এবং আপনাকে বিশ্বাস করে to এটি প্রকারের সুরক্ষা সিস্টেমের স্পষ্ট ওভাররাইড এবং সংকলকরা মূলত যে কোনও ধরণের রূপান্তর গ্রহণ করতে হয়। সি স্টাইলের কাস্টগুলি এড়ানো উচিত, এগুলি খুব শক্তিশালী। সি ++ এর মতো কাস্ট ব্যবহার করুন static_castযা আপনি যদি এমন কিছু করার চেষ্টা করছেন যা বোঝা যায় না তবে অভিযোগ করবে।
ফ্রেঞ্চোইস অ্যান্ডরিয়াক

@ রিচার্ডক্রিটেন ভুল ভাষা - কোনও ত্রুটি নেই Godbolt.org/z/RmFpgN সি ++ চুদা সাধারণত হিসাবে সুস্পষ্ট কাস্ট প্রয়োজন।
P__J__

উত্তর:


4

আমি কি পুরো জিনিসটি সম্পর্কে কিছু মিস করছি এবং এমএসভিসি কোনও সতর্কতা উত্থাপন করার কোনও নির্দিষ্ট কারণ নেই? ** অকার্যকর ** থেকে ভাসমান ** রূপান্তর করার সময় এমএসভিসি একটি সতর্কতা তৈরি করে

Castালাই ছাড়াই এই নিয়োগটি সীমাবদ্ধতা লঙ্ঘন, সুতরাং একটি মানক কমপ্লায়েন্ট কম্পাইলার একটি সতর্কতা বা ত্রুটি মুদ্রণ করবে। তবে এমএসভিসি সম্পূর্ণরূপে সি বাস্তবায়ন করছে না।

নোটের আরেকটি বিষয়: আমি যদি a = b এর স্পষ্ট রূপান্তর a = (অকার্যকর **) বি দিয়ে প্রতিস্থাপন করি তবে সংকলকগুলির মধ্যে কেউ সতর্কতা ছুঁড়ে না ফেলে। আমি ভেবেছিলাম এটি একটি অবৈধ castালাই হওয়া উচিত, তবে কেন কোনও সতর্কতা থাকবে না?

কাস্টের মাধ্যমে পয়েন্টার রূপান্তরগুলি কিছু পরিস্থিতিতে অনুমোদিত। সি স্ট্যান্ডার্ডটি 6.3.2.3p7 বিভাগে নিম্নলিখিতটি বলেছে:

কোনও অবজেক্ট টাইপের একটি পয়েন্টারকে পয়েন্টারটিতে আলাদা আলাদা অবজেক্ট টাইপের রূপান্তর করা যেতে পারে। যদি ফলাফল প্রাপ্ত পয়েন্টারটি রেফারেন্স করা টাইপের জন্য সঠিকভাবে সংযুক্ত না হয়, তবে আচরণটি সংজ্ঞায়িত। অন্যথায়, যখন আবার ফিরে রূপান্তরিত হয়, ফলাফলটি মূল পয়েন্টারের সমান তুলনা করে। যখন কোনও অবজেক্টের পয়েন্টারকে পয়েন্টারকে একটি অক্ষর টাইপের রূপান্তর করা হয়, ফলাফলটি বস্তুটির সর্বনিম্ন সম্বোধিত বাইটে নির্দেশ করে। ফলাফলের ক্রমবৃদ্ধি, অবজেক্টের আকার পর্যন্ত অবজেক্টের অবশিষ্ট বাইটগুলিতে পয়েন্টার দেয়।

সুতরাং কোনও বিন্যাস সংক্রান্ত সমস্যা না থাকলে আপনি পয়েন্টার ধরণের মধ্যে রূপান্তর করতে পারবেন এবং কেবলমাত্র রূপান্তরিত করুন (লক্ষ্যটি যদি না হয় তবে char *)।

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

...

এটি কি এনভিআইডিআইএর শেষ দিকে ঝিমঝিম কাজ নাকি আমি আবার কিছু হারিয়ে যাচ্ছি?

সম্ভবত, এই ফাংশনটি প্রদত্ত পয়েন্টারটিকে ডিফারেন্স করছে এবং কিছু বরাদ্দকৃত মেমরির ঠিকানা লিখছে। এর অর্থ হ'ল এটি একটি লেখার চেষ্টা করছে float *যেন এটি একটি void *। এটি এ / থেকে সাধারণত রূপান্তর হিসাবে একই নয় void *। কঠোরভাবে বলতে গেলে এটি অপরিজ্ঞাত আচরণের মতো দেখায়, যদিও এটি "কাজ করে" কারণ আধুনিক x86 প্রসেসরগুলি (যখন রিয়েল মোডে থাকে না) সমস্ত পয়েন্টার ধরণের জন্য একই উপস্থাপনা ব্যবহার করে।


@ ডিবুশ খুব তথ্যপূর্ণ, আপনাকে ধন্যবাদ! এটি কাজ করে কেন এটি কাজ করে তা আমি পেয়েছি। তবুও, প্রয়োজনীয় সংকলন &d_Aনা থাকায় বেশিরভাগ সংকলকরা কোনও সতর্কতা বা এমনকী ত্রুটি ছুঁড়ে দেবে না ?
ক্যাপ্টেনপ্রোটন 42

3
আপনি কীভাবে এটি ব্যাখ্যা করেন সে সম্পর্কে সতর্ক হন, আপনি যদি সি + সি
+++
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.