সি তে মেমরি লেআউট গঠন করুন


86

আমার সি # পটভূমি রয়েছে। আমি সি এর মতো নিম্ন স্তরের ভাষার খুব নবী

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

আফাইক, সি structডিফল্টরূপে মেমরি লেআউটটিকে পুনরায় অর্ডার বা সারিবদ্ধ করে না । তবে, আমি শুনেছি যে এখানে কিছু ব্যতিক্রম আছে যা খুঁজে পাওয়া খুব কঠিন hard

সি এর মেমরি লেআউট আচরণ কী? কি পুনরায় অর্ডার / প্রান্তিককরণ করা উচিত এবং না?

উত্তর:


111

সি-তে, সংকলককে প্রতিটি আদিম ধরণের জন্য কিছু প্রান্তিককরণ নির্ধারণ করার অনুমতি দেওয়া হয়। সাধারণত প্রান্তিককরণ হ'ল ধরণের আকার। তবে এটি সম্পূর্ণ বাস্তবায়ন-নির্দিষ্ট।

প্যাডিং বাইটগুলি প্রবর্তিত হয় যাতে প্রতিটি বস্তু সঠিকভাবে প্রান্তিক হয়। পুনরায় অর্ডার করার অনুমতি নেই।

সম্ভবত প্রতিটি দূরবর্তী আধুনিক সংকলক প্রয়োগ #pragma packযা প্যাডিংয়ের উপরে নিয়ন্ত্রণের অনুমতি দেয় এবং এটি প্রোগ্রামটিকে এবিআইয়ের সাথে মেনে চলতে দেয়। (যদিও এটি কঠোরভাবে মানসম্পন্ন নয়)

C99 থেকে .76.7.2.1:

12 একটি কাঠামো বা ইউনিয়ন অবজেক্টের প্রতিটি নন-বিট-ফিল্ড সদস্য তার প্রকারের সাথে যথাযথভাবে প্রয়োগকরণ-সংজ্ঞায়িত পদ্ধতিতে সংযুক্ত থাকে।

১৩ স্ট্রাকচার অবজেক্টের মধ্যে, নন-বিট-ফিল্ড সদস্য এবং বিট-ফিল্ডে থাকা ইউনিটগুলির ঠিকানা রয়েছে যা সেগুলি ঘোষিত হওয়ার ক্রমে বৃদ্ধি পায়। কাঠামোগত বস্তুর পয়েন্টার, যথাযথ রূপান্তরিত, এর প্রাথমিক সদস্যকে নির্দেশ করে (বা যদি সেই সদস্যটি বিট-ফিল্ড হয়, তবে এটি যে ইউনিটে থাকে সেখানে) এবং তার বিপরীতে। কোনও কাঠামোর অবজেক্টের মধ্যে নামবিহীন প্যাডিং থাকতে পারে, তবে এটির শুরুতে নয়।


4
কিছু সংকলক (অর্থাত্ জিসিসি) #pragma packশব্দার্থবিদ্যার উপর আরও সূক্ষ্ম নিয়ন্ত্রণের সাথে একই প্রভাব প্রয়োগ করে ।
ক্রিস লুটজ

21
ডাউনটা দেখে আমি অবাক হয়েছি। কেউ কি ত্রুটিটি নির্দেশ করতে পারে?
পোটোসওয়টার

4
সি 11 এরও রয়েছে _Alignas
ইডমিয়ান

117

এটি বাস্তবায়ন-সুনির্দিষ্ট, তবে বাস্তবে নিয়মটি (অনুপস্থিতিতে #pragma packবা এর মতো) হ'ল:

  • স্ট্রাক্ট সদস্যরা তাদের ঘোষিত ক্রমে সংরক্ষণ করা হয়। (এটি এখানে পূর্বে উল্লিখিত হিসাবে C99 স্ট্যান্ডার্ড দ্বারা প্রয়োজনীয়)
  • যদি প্রয়োজন হয় তবে সঠিক অ্যালাইনমেন্ট নিশ্চিত করার জন্য প্রতিটি কাঠামোর সদস্যের আগে প্যাডিং যুক্ত করা হয়।
  • প্রতিটি আদিম টাইম টিতে sizeof(T)বাইটগুলির প্রান্তিককরণ প্রয়োজন ।

সুতরাং, নিম্নলিখিত কাঠামো দেওয়া:

  • ch1 অফসেটে 0
  • সারিবদ্ধ করার জন্য একটি প্যাডিং বাইট প্রবেশ করানো হয়েছে ...
  • s অফসেট 2 এ
  • ch2 অফসেট 4 এ অবিলম্বে এস
  • সারিবদ্ধ করতে 3 টি প্যাডিং বাইট সন্নিবেশ করা হয়েছে ...
  • ll অফসেট 8
  • i LL এর ঠিক পরে, অফসেটে 16 রয়েছে
  • শেষে 4 টি প্যাডিং বাইট যুক্ত করা হয়েছে যাতে সামগ্রিক কাঠামোটি 8 বাইটের একাধিক হয়। আমি এটি একটি 64-বিট সিস্টেমে পরীক্ষা করেছি: 32-বিট সিস্টেমগুলি স্ট্র্টকে 4-বাইট প্রান্তিককরণের অনুমতি দিতে পারে।

তাই sizeof(ST)24।

প্যাডিং এড়াতে সদস্যদের পুনর্বিন্যাসের মাধ্যমে এটি 16 বাইটে হ্রাস করা যেতে পারে:


4
যদি প্রয়োজনীয় হয়, প্যাডিং আগে যুক্ত করা হবে ... আরও পরে পছন্দ। charআপনার উদাহরণে একটি চূড়ান্ত সদস্য যুক্ত করুন সেরা ।
Deduplicator

9
একটি আদিম ধরণের অগত্যা sizeof(T)বাইটগুলির প্রান্তিককরণের প্রয়োজন হয় না । উদাহরণস্বরূপ, doubleসাধারণ 32-বিট আর্কিটেকচারের জন্য 8 বাইট হয় তবে প্রায়শই কেবল 4-বাইট প্রান্তিককরণ প্রয়োজন । তদ্ব্যতীত, কাঠামোর শেষে প্যাডিং কেবলমাত্র বিস্তৃত কাঠামোর সদস্যের প্রান্তিককরণে প্যাড করে। উদাহরণস্বরূপ, 3 চর ভেরিয়েবলের স্ট্রাক্টে কোনও প্যাডিং থাকতে পারে না।
ম্যাট

4
@ ডান04, আকারের (টি) এর উত্থানের ক্রমে স্ট্রাউটগুলি বিন্যাস করা ভাল অনুশীলন হবে। এটি করার জন্য কোনও ডাউনসাইড থাকবে?
রোহিতম্যাট

11

ডেটা সারিবদ্ধকরণের আরও ভাল ধারণা পেতে আপনি ডেটা স্ট্রাকচার প্রান্তিককরণ উইকিপিডিয়া নিবন্ধটি পড়তে শুরু করতে পারেন ।

থেকে Wikipedia নিবন্ধটি :

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

CC.৫৪.৮ থেকে জিসিসির ডকুমেন্টেশনের স্ট্রাকচার-প্যাকিং প্রগমাস :

মাইক্রোসফ্ট উইন্ডোজ সংকলকগুলির সাথে সামঞ্জস্যের জন্য, জিসিসি # প্রগমা নির্দেশিকাগুলির একটি সেটকে সমর্থন করে যা কাঠামোর সদস্যদের সর্বাধিক সারিবদ্ধকরণ (শূন্য-প্রস্থ বিটফিল্ডগুলি ব্যতীত), ইউনিয়ন এবং ক্লাসগুলি পরে সংজ্ঞায়িত করে। নীচের এন মানটি সর্বদা দু'জনের একটি ছোট শক্তি হওয়া আবশ্যক এবং বাইটগুলিতে নতুন প্রান্তিককরণ নির্দিষ্ট করে।

  1. #pragma pack(n) কেবল নতুন প্রান্তিককরণ সেট করে।
  2. #pragma pack() সংকলন শুরু হওয়ার পরে কার্যকর হয়েছিল এমনটির সাথে প্রান্তিককরণ সেট করে (কমান্ড লাইন বিকল্প -fpack -ruct দেখুন [=] কোড জেনার বিকল্পগুলি দেখুন)।
  3. #pragma pack(push[,n]) অভ্যন্তরীণ স্ট্যাকের বর্তমান প্রান্তিককরণ সেটিংসকে ধাক্কা দেয় এবং তারপরে বিকল্পভাবে নতুন প্রান্তিককরণ সেট করে।
  4. #pragma pack(pop)অভ্যন্তরীণ স্ট্যাকের শীর্ষে সংরক্ষণ করা যেকোনোটিতে প্রান্তিককরণ সেটিংস পুনরুদ্ধার করে (এবং সেই স্ট্যাকের প্রবেশটি সরিয়ে দেয়)। নোট যে #pragma pack([n])এই অভ্যন্তরীণ স্ট্যাক প্রভাবিত করে না; সুতরাং #pragma pack(push) একাধিক #pragma pack(n) উদাহরণ অনুসরণ করা এবং একটি একক দ্বারা চূড়ান্ত করা সম্ভব #pragma pack(pop)

কিছু লক্ষ্য, যেমন i386 এবং পাওয়ারপিসি, এমএস_স্ট্রাক্টকে সমর্থন করে #pragmaযা ডকুমেন্ট হিসাবে একটি কাঠামো আউট দেয় __attribute__ ((ms_struct))

  1. #pragma ms_struct on ঘোষিত কাঠামোর জন্য বিন্যাস চালু করে।
  2. #pragma ms_struct off ঘোষিত কাঠামোর জন্য বিন্যাস বন্ধ করে দেয়।
  3. #pragma ms_struct reset ডিফল্ট লেআউটে ফিরে যায়।

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