সি # তে বুলিয়ান এর আকার কত? এটি কি সত্যই 4-বাইট লাগে?


137

বাইটস এবং বুলিয়ানগুলির অ্যারে সহ আমার দুটি স্ট্রাক্ট রয়েছে:

using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct struct1
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] values;
}

[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct struct2
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public bool[] values;
}

এবং নিম্নলিখিত কোড:

class main
{
    public static void Main()
    {
        Console.WriteLine("sizeof array of bytes: "+Marshal.SizeOf(typeof(struct1)));
        Console.WriteLine("sizeof array of bools: " + Marshal.SizeOf(typeof(struct2)));
        Console.ReadKey();
    }
}

এটি আমাকে নিম্নলিখিত ফলাফল দেয়:

sizeof array of bytes: 3
sizeof array of bools: 12

দেখে মনে হচ্ছে যে booleanএটিতে 4 বাইট স্টোরেজ লাগে। আদর্শভাবে একটি boolean কেবলমাত্র একটি বিট নেয় ( falseবা true, 0বা 1, ইত্যাদি)।

এখানে কি হচ্ছে? কি booleanধরনের সত্যিই তাই অদক্ষ?


7
এটি হোল্ড-কারণগুলির চলমান যুদ্ধের মধ্যে সবচেয়ে ব্যঙ্গাত্মক সংঘাতগুলির মধ্যে একটি: জন এবং হান্সের দুটি দুর্দান্ত উত্তর সবেমাত্র এটি তৈরি করেছে, যদিও এই প্রশ্নের উত্তরগুলি তথ্য, রেফারেন্সের পরিবর্তে প্রায় সম্পূর্ণরূপে মতামতের উপর ভিত্তি করে থাকবে, বা নির্দিষ্ট দক্ষতা।
তাব

12
@ টাও: আমার অনুমান যে নিকটতম ভোটের জবাব উত্তরগুলির কারণে ছিল না তবে ওপি'র মূল সুরটি যখন তারা প্রথম প্রশ্নটি প্রকাশ করেছিল - তারা স্পষ্টভাবে লড়াই শুরু করার ইচ্ছা করেছিল এবং এখনই মুছে ফেলা মন্তব্যে প্রকাশ্যভাবে এটি প্রকাশ করেছিল। বেশিরভাগ ক্রুফটটি গালিগাটির নীচে ছড়িয়ে গেছে, তবে আমি কী বলতে চাইছি তার একটি ঝলক পেতে পুনর্বিবেচনার ইতিহাসটি দেখুন।
বোল্টক্লক

1
বিটআর্রে ব্যবহার করছেন না কেন?
21'50

উত্তর:


242

Bool, টাইপ ভাষা রানটাইম মধ্যে অনেক বেমানান পছন্দ সঙ্গে একটি ছককাটা ইতিহাস রয়েছে। ডেনিস রিচি, সি ভাষা আবিষ্কার করেছেন এমন লোকটি তৈরি করেছিলেন anতিহাসিক নকশা-পছন্দ দিয়ে এটি শুরু হয়েছিল। এটা একটা ছিল না bool, ধরন, বিকল্প ছিল int- এ যেখানে 0 একটি মান প্রতিনিধিত্ব করে মিথ্যা এবং অন্য কোন মান হিসেবে বিবেচনা করা হয় সত্য

এই পছন্দটি Winapi এগিয়ে বাহিত হয়, ব্যবহার pinvoke করার প্রাথমিক কারণ, এটা একটি typedef জন্য রয়েছে BOOLযা সি কম্পাইলার এর জন্য উপনাম হল int- এ শব্দ। আপনি একটি সুনির্দিষ্ট [MarshalAs] অ্যাট্রিবিউট তারপর একটি C # এর প্রয়োগ না থাকে তাহলে bool, একটি bool রূপান্তরিত হয়, এইভাবে একটি ক্ষেত্র যে 4 বাইট দীর্ঘ উত্পাদক।

আপনি যাই করুন না কেন, আপনার স্ট্রাক্ট ঘোষণার সাথে আপনি যে ভাষাটি ব্যবহার করছেন সে ভাষায় রানটাইম পছন্দের সাথে মিল থাকতে হবে। যেমনটি উল্লেখ করা হয়েছে, উইনাপির জন্য BOOL তবে বেশিরভাগ সি ++ বাস্তবায়ন বাইট বেছে নিয়েছে , বেশিরভাগ COM অটোমেশন ইন্টারপ VARIANT_BOOL ব্যবহার করে যা সংক্ষিপ্ত

প্রকৃত একটি C # এর আকার boolএক বাইট। সিএলআরের একটি শক্তিশালী ডিজাইন লক্ষ্য এটি আপনি খুঁজে পেতে পারেন না cannot লেআউট একটি বাস্তবায়ন বিশদ যা প্রসেসরের উপর খুব বেশি নির্ভর করে। প্রসেসরগুলি ভেরিয়েবলের ধরণ এবং প্রান্তিককরণ সম্পর্কে খুব পছন্দসই, ভুল পছন্দগুলি উল্লেখযোগ্যভাবে পারফরম্যান্সকে প্রভাবিত করতে পারে এবং রানটাইম ত্রুটির কারণ হতে পারে। লেআউটটিকে অন্বেষণযোগ্য করে,। নেট একটি সর্বজনীন টাইপ সিস্টেম সরবরাহ করতে পারে যা প্রকৃত রানটাইম বাস্তবায়নের উপর নির্ভর করে না।

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

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

সি # সংকলক অন্যথায় আপনাকে লজ্জা দেয় না যে এটি 1 বাইট, ব্যবহার লাগে sizeof(bool)। কোনও ক্ষেত্র রানটাইমের সময় কয়টি বাইট নেয়, এটি এখনও চমকপ্রদ ভবিষ্যদ্বাণীকারী নয়, সিএলআরকে .NET মেমরির মডেলটি প্রয়োগ করতে হবে এবং এটি প্রতিশ্রুতি দেয় যে সহজ পরিবর্তনশীল আপডেটগুলি পারমাণবিক । এর জন্য ভেরিয়েবলগুলি মেমরিতে সঠিকভাবে প্রান্তিক হওয়া প্রয়োজন যাতে প্রসেসর এটি একটি একক মেমরি-বাস চক্রের সাথে আপডেট করতে পারে। খুব সুন্দর, একটি বুলের জন্য মেমরিতে আসলে 4 বা 8 বাইটের প্রয়োজন হয়। পরবর্তী সদস্যটি সঠিকভাবে প্রান্তিক করা আছে তা নিশ্চিত করতে অতিরিক্ত প্যাডিং যুক্ত করা হয়েছিল ।

সিএলআর প্রকৃতপক্ষে লেআউটটিকে অপরিবর্তনযোগ্য হওয়ার সুবিধা গ্রহণ করে, এটি একটি শ্রেণির বিন্যাসকে অনুকূলিত করতে পারে এবং ক্ষেত্রগুলি পুনরায় সাজিয়ে তুলতে পারে যাতে প্যাডিং হ্রাস করা যায়। সুতরাং, বলুন, আপনার যদি একটি বুল + ইনট + বুল সদস্য সহ একটি ক্লাস থাকে তবে এটির জন্য 1 + (3) + 4 + 1 + (3) মেমরির বাইট লাগবে, (3) মোট 12 এর জন্য প্যাডিং হবে বাইট। 50% বর্জ্য। স্বয়ংক্রিয় বিন্যাস 1 + 1 + (2) + 4 = 8 বাইটে পুনরায় সাজানো। কেবলমাত্র একটি শ্রেণিতে স্বয়ংক্রিয় লেআউট থাকে, স্ট্রাক্টের ডিফল্ট অনুসারে ক্রমিক লেআউট থাকে।

আরও নির্লজ্জভাবে, একটি বুলের একটি সি সি ++ প্রোগ্রামে প্রায় 32 বাইটের প্রয়োজন হতে পারে একটি আধুনিক সি ++ সংকলক যা AVX নির্দেশনা সেট সমর্থন করে। যা একটি 32-বাইট প্রান্তিককরণ প্রয়োজনীয়তা আরোপ করে, বুল ভেরিয়েবলটি 31 বাইট প্যাডিং সহ শেষ হতে পারে। এছাড়াও। নেট জুইটার সিমডি নির্দেশিকা নির্গত না করার মূল কারণ, স্পষ্টভাবে মোড়ানো না থাকলে এটি সারিবদ্ধতা গ্যারান্টি পেতে পারে না।



2
আগ্রহী কিন্তু অজ্ঞাত পাঠকের জন্য, আপনি কি স্পষ্ট করে বলবেন যে শেষ অনুচ্ছেদে সত্যিই 32 বাইট পড়তে হবে এবং বিটগুলি নয় ?
সিলি ফ্রিক

3
আমি কেন কেবল এই সমস্তটি পড়ি তা নিশ্চিত নই (কেননা আমার এত বেশি বিবরণের প্রয়োজন নেই) তবে তা আকর্ষণীয় এবং ভালভাবে লেখা।
ফ্রাঙ্ক ভি

2
@Silly - এটা বাইট । এভিএক্স একক নির্দেশাবলীতে 8 ভাসমান পয়েন্টের মানগুলিতে গণিত করতে 512 বিট ভেরিয়েবল ব্যবহার করে। যেমন একটি 512 বিট পরিবর্তনশীল 32 থেকে প্রান্তিককরণ প্রয়োজন
হান্স পাসান্ত

3
কি দারুন! একটি পোস্ট বুঝতে জাহান্নামের অনেক বিষয় দিয়েছে। এজন্য আমি কেবল শীর্ষ প্রশ্নগুলি পড়তে পছন্দ করি।
চৈতন্য গডকরি

151

প্রথমত, এটি কেবল ইন্টারপের জন্য আকার। এটি অ্যারের পরিচালিত কোডে আকারটি উপস্থাপন করে না। এটি প্রতি 1 বাইট bool- কমপক্ষে আমার মেশিনে। আপনি এই কোডটি দিয়ে এটি নিজের জন্য পরীক্ষা করতে পারেন:

using System;
class Program 
{ 
    static void Main(string[] args) 
    { 
        int size = 10000000;
        object array = null;
        long before = GC.GetTotalMemory(true); 
        array = new bool[size];
        long after = GC.GetTotalMemory(true); 

        double diff = after - before; 

        Console.WriteLine("Per value: " + diff / size);

        // Stop the GC from messing up our measurements 
        GC.KeepAlive(array); 
    } 
}

এখন, মান অনুসারে অ্যারে মার্শেলিংয়ের জন্য, যেমন আপনি রয়েছেন, ডকুমেন্টেশনটি বলে:

মার্শালআস্যাট্রিবিউট.ভ্যালু বৈশিষ্ট্যটি সেট করা থাকলে ByValArrayঅ্যারেতে উপাদানের সংখ্যা চিহ্নিত করতে সাইজকনস্ট ফিল্ডটি সেট করতে হবে। ArraySubTypeক্ষেত্র ঐচ্ছিকরূপে ধারণ করতে পারে UnmanagedTypeঅ্যারে উপাদানের যখন এটি স্ট্রিং ধরনের মধ্যে পার্থক্য করা প্রয়োজন। আপনি এটি UnmanagedTypeকেবল এমন একটি অ্যারেতে ব্যবহার করতে পারেন যাগুলির উপাদানগুলি কোনও কাঠামোর ক্ষেত্র হিসাবে প্রদর্শিত হয়।

সুতরাং আমরা তাকান ArraySubType, এবং এর ডকুমেন্টেশন রয়েছে:

UnmanagedTypeঅ্যারের উপাদানগুলির ধরণ নির্দিষ্ট করতে আপনি গণনা থেকে কোনও মানটিতে এই পরামিতিটি সেট করতে পারেন । যদি কোনও প্রকার নির্দিষ্ট না করা থাকে তবে পরিচালিত অ্যারের উপাদানের প্রকারের সাথে সম্পর্কিত ডিফল্ট অযৌক্তিকভাবে ব্যবহৃত টাইপ ব্যবহার করা হয়।

এখন তাকিয়ে UnmanagedTypeআছে, আছে:

বুল
এ 4-বাইট বুলিয়ান মান (সত্য! = 0, মিথ্যা = 0) এটি Win32 BOOL টাইপ।

সুতরাং boolএটির জন্য ডিফল্ট , এবং এটি 4 বাইট কারণ এটি উইন 32 বিওএল টাইপের সাথে সামঞ্জস্যপূর্ণ - সুতরাং আপনি যদি BOOLঅ্যারের প্রত্যাশা করে কোডের সাথে ইন্টারঅপেট করছেন তবে এটি আপনি যা চান ঠিক তা করে।

এখন আপনি পরিবর্তে ArraySubTypeহিসাবে নির্দিষ্ট করতে পারেন I1, যা হিসাবে নথিভুক্ত করা হয়:

একটি 1 বাইট স্বাক্ষরিত পূর্ণসংখ্যা। আপনি এই সদস্যটিকে বুলিয়ান মানকে 1-বাইট, সি-স্টাইলের বুলে রূপান্তর করতে পারেন (সত্য = 1, মিথ্যা = 0)।

সুতরাং আপনি যে কোডটির সাথে আন্তঃসংযোগ করছেন তাতে যদি প্রতি মূল্য 1 বাইট প্রত্যাশিত হয় তবে কেবল ব্যবহার করুন:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
public bool[] values;

আপনার কোডটি তখন প্রত্যাশা অনুযায়ী মান হিসাবে 1 বাইট গ্রহণ করবে show

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