স্টাড :: বিট_কাস্ট সাথে স্ট্যান্ড :: অ্যারে


14

তার সাম্প্রতিক আলাপ ইন "আধুনিক সি প্রকার punning ++," তৈমুর Doumler বলেন যে std::bit_castকরতে বিট একটি নিক্ষেপ ব্যবহার করা যাবে না floatএকটি মধ্যে unsigned char[4]কারণ সি-শৈলী অ্যারে একটি ফাংশন থেকে ফিরে যাবে না। আমাদের হয় std::memcpyসি ++ 23 (বা তারপরে) অবধি ব্যবহার করা বা অপেক্ষা করা উচিত যখন এর মতো কিছু reinterpret_cast<unsigned char*>(&f)[i]ভাল সংজ্ঞায়িত হয়ে যায়।

সি ++ 20, আমরা একটি ব্যবহার করতে পারেন std::arrayসঙ্গে std::bit_cast,

float f = /* some value */;
auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f);

এর পরিবর্তে সি-স্টাইলের অ্যারের থেকে বাইট পেতে হবে float?

উত্তর:


15

হ্যাঁ, এটি সমস্ত বড় সংকলকগুলিতে কাজ করে এবং যতদূর আমি স্ট্যান্ডার্ডের দিকে তাকানো থেকে বলতে পারি এটি পোর্টেবল এবং কাজের গ্যারান্টিযুক্ত।

প্রথমত, std::array<unsigned char, sizeof(float)>একটি সামগ্রিক ( https://eel.is/c++traft/array#overview-2 ) হিসাবে গ্যারান্টিযুক্ত । থেকে এই অনুসরণ করে এটি ঠিক ঝুলিতে sizeof(float)সংখ্যা charভিতরে গুলি (সাধারণত যেমন char[], যদিও afaics মান এই বিশেষ বাস্তবায়ন জনাদেশ না - কিন্তু এটা বলা আছে উপাদানের সংলগ্ন হতে হবে) এবং অন্য কোনও অতিরিক্ত অ স্ট্যাটিক সদস্যদের থাকতে পারে না।

এটি তাই তুচ্ছভাবে অনুলিপিযোগ্য এবং এর আকারও এর সাথে মেলে float

এই দুটি সম্পত্তি আপনাকে bit_castতাদের মধ্যে অনুমতি দেয় ।


3
নোটটি যেটি struct X { unsigned char elems[5]; };আপনি উল্লেখ করছেন সেই বিধিটিকে সন্তুষ্ট করে Note এটি অবশ্যই 4 টি পর্যন্ত উপাদান দিয়ে তালিকাভুক্ত করা যেতে পারে। এটা করতে পারেন এছাড়াও তালিকা-সক্রিয়া 5 উপাদানের সঙ্গে থাকুন। আমি মনে করি না যে কোনও মানক গ্রন্থাগার প্রয়োগকারী লোককে এটি করতে যথেষ্ট পরিমাণে ঘৃণা করে তবে আমি মনে করি এটি প্রযুক্তিগতভাবে উপযুক্ত forma
ব্যারি

ধন্যবাদ! - ব্যারি, আমি একদম ঠিক মনে করি না। স্ট্যান্ডার্ডটি বলে: "এন পর্যন্ত উপাদানগুলির সাথে তালিকা-সূচনা করা যেতে পারে"। আমার ব্যাখ্যাটি হ'ল "পর্যন্ত" বোঝানো হয় "এর চেয়ে বেশি কিছু নয়"। যার অর্থ আপনি করতে পারবেন না elems[5]। এবং এই মুহুর্তে আমি দেখতে পাচ্ছি না আপনি কীভাবে একটি সামগ্রিক সমাপ্ত হতে পারেন sizeof(array<char, sizeof(T)>) != sizeof(T)?
তৈমুর ডমলার

আমি বিশ্বাস করি যে নিয়মের উদ্দেশ্য ("একটি সামগ্রিক যা তালিকা-সূচনা হতে পারে ...") হয় অনুমতি দেয় struct X { unsigned char c1, c2, c3, c4; };বা struct X { unsigned char elems[4]; };- সুতরাং যখন চরগুলি সেই সামগ্রীর উপাদান হওয়া দরকার, এটি তাদের হয় সরাসরি একত্রিত সামগ্রীর উপাদান হতে দেয় বা একটি একক উপ-সমষ্টি উপাদানসমূহ।
তৈমুর ডমলার

2
@ টিমুর "অবধি" "" এর চেয়ে বেশি "বোঝায় না। একইভাবে যেভাবে P -> Q!P
ব্যারি

1
সমষ্টিতে ঠিক 4 টি উপাদানের অ্যারে ব্যতীত কিছু না থাকলেও নিজের কোনও arrayপ্যাডিং থাকবে না এমন কোনও গ্যারান্টি নেই । এর বাস্তবায়নে প্যাডিং নাও থাকতে পারে (এবং এমন কোনও বাস্তবায়ন যা নিষ্ক্রিয় হিসাবে বিবেচনা করা উচিত), তবে কোনও গ্যারান্টি নেই যে এটি arrayনিজেই করবে না।
নিকল বোলাস

6

গৃহীত উত্তরটি ভুল কারণ এটি প্রান্তিককরণ এবং প্যাডিংয়ের সমস্যাগুলি বিবেচনা করতে ব্যর্থ।

প্রতি [অ্যারের] / 1-3 :

হেডার <array>বস্তুর নির্দিষ্ট আকার সিকোয়েন্স জমা করার জন্য একটি শ্রেণী টেমপ্লেট সংজ্ঞায়িত করে। একটি অ্যারে একটি স্বচ্ছ পাত্রে। এর একটি দৃষ্টান্ত array<T, N>দোকানে Nধরনের উপাদান T, যাতে size() == Nএকটি পরিবর্তিত হয়।

একটি অ্যারে হ'ল একটি সমষ্টি যা এমন N উপাদানগুলির সাথে তালিকাতে শুরু করা যেতে পারে যার প্রকারভেদে রূপান্তরযোগ্য T

একটি অ্যারে একটি ধারক এবং বিপরীতমুখী ধারক ( [container.requirements]) এর সমস্ত প্রয়োজনীয়তা পূরণ করে , ব্যতীত ডিফল্ট নির্মান অ্যারে বস্তুটি খালি নয় এবং সেই স্বাপের স্থির জটিলতা নেই। একটি অ্যারে একটি সিকোয়েন্স পাত্রে কিছু প্রয়োজনীয়তা পূরণ করে। বিবরণগুলি এখানে কেবলমাত্র অ্যারেতে পরিচালিত অপারেশনের জন্য সরবরাহ করা হয়েছে যা এই সারণির একটিতে বর্ণিত হয়নি এবং যেখানে অতিরিক্ত শব্দার্থক তথ্য রয়েছে সেখানে পরিচালনার জন্য।

মানকটির আসলে প্রয়োজন হয় না std::array জন্য এক ধরণের জনসাধারণের ডেটা সদস্যেরT[N] , তাই তাত্ত্বিকভাবে এটি সম্ভব sizeof(To) != sizeof(From)বা বা is_­trivially_­copyable_­v<To>

যদিও এটি অনুশীলনে কাজ না করে তবে আমি অবাক হব।


2

হ্যাঁ.

যে আচরণের বর্ণনা দেয় সেই কাগজ অনুসারে std::bit_cast, এবং এর প্রস্তাবিত বাস্তবায়ন যতক্ষণ না উভয় ধরণেরই আকার একই এবং তুচ্ছভাবে অনুলিপিযোগ্য কাস্ট সফল হতে হবে।

এর সরলীকৃত বাস্তবায়ন std::bit_castএরকম কিছু হওয়া উচিত:

template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
    static_assert(sizeof(Dest) == sizeof(Source));
    static_assert(std::is_trivially_copyable<Dest>::value);
    static_assert(std::is_trivially_copyable<Source>::value);

    Dest dest;
    std::memcpy(&dest, &source, sizeof(dest));
    return dest;
}

যেহেতু একটি ভাসা (4 বাইট) এবং সমস্ত সম্মানের unsigned charসাথে size_of(float)সম্মানের একটি অ্যারে , অন্তর্নিহিত std::memcpyসম্পন্ন করা হবে। সুতরাং, ফলস্বরূপ অ্যারেতে প্রতিটি উপাদান ফ্লোটের একটানা বাইট হবে।

এই আচরণটি প্রমাণ করার জন্য, আমি কম্পাইলার এক্সপ্লোরারে একটি ছোট উদাহরণ লিখেছিলাম যা আপনি এখানে চেষ্টা করতে পারেন: https://godbolt.org/z/4G21zS । ফ্লোট 5.0 সঠিকভাবে বাইটের অ্যারে হিসাবে সংরক্ষণ করা হয় ( Ox40a00000) যা বিগ এন্ডিয়ানের সেই ফ্লোট নম্বরটির হেক্সাডেসিমাল উপস্থাপনার সাথে মিলে যায়


আপনি কি নিশ্চিত যে std::arrayপ্যাডিং বিট ইত্যাদি না রাখার নিশ্চয়তা রয়েছে?
এলএফ

1
দুর্ভাগ্যক্রমে, কিছু কোড যে কেবলমাত্র কাজ করে তা এতে কোনও ইউবি বোঝায় না। উদাহরণস্বরূপ, আমরা লিখতে auto bits = reinterpret_cast<std::array<unsigned char, sizeof(float)>&>(f)এবং ঠিক একই আউটপুট পেতে পারি । এটি কিছু প্রমাণ করে?
এভগ

স্পেসিফিকেশন অনুসারে @ এলএফ: কন্টিগুইওসকন্টেইনারেরstd::array প্রয়োজনীয়তা পূরণ করে (যেহেতু সি +++ )
ম্যানুয়েল গিল

1
@ ম্যানুয়েলগিল: std::vectorএকই মানদণ্ডকেও সন্তুষ্ট করে এবং স্পষ্টতই এখানে ব্যবহার করা যাবে না। std::arrayশ্রেণীর অভ্যন্তরীণ উপাদানগুলি (কোনও ক্ষেত্রে) ধারণ করে এমন কিছু প্রয়োজন রয়েছে যা এটি অভ্যন্তরীণ অ্যারেতে সরল পয়েন্টার হতে বাধা দেয়? (ভেক্টরের মতো, যার আকারও রয়েছে, যার অ্যারেটি কোনও ক্ষেত্রের মধ্যে রাখার প্রয়োজন নেই)
ফিরদা

@ ফিরদা মোট std::arrayকার্যকরভাবে কার্যকরভাবে এটি অভ্যন্তরের উপাদানগুলি সংরক্ষণ করার জন্য প্রয়োজন তবে আমি লেআউট সমস্যা নিয়ে চিন্তিত।
এলএফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.