স্ট্রাক্টের আকার কেন প্রতিটি সদস্যের আকারের সমান?


697

কেন sizeofঅপারেটর কাঠামোর সদস্যদের মোট আকারের চেয়ে কোনও কাঠামোর জন্য আকার বড় করে দেয় ?


14
মেমরি প্রসারিতকরণের জন্য এই সি এফএকিউ দেখুন। c-faq.com/struct/align.esr.html
রিচার্ড চেম্বারস

48
উপাখ্যান: একটি আসল কম্পিউটার ভাইরাস ছিল যা হোস্ট প্রোগ্রামে স্ট্রাক্ট প্যাডিংয়ের মধ্যে কোড রেখেছিল।
এলাজার

4
@ এলাজার এটি চিত্তাকর্ষক! আমি কখনই এ জাতীয় ক্ষুদ্র অঞ্চলগুলি কোনও কিছুর জন্য ব্যবহার করা সম্ভব ভাবিনি। আপনি কি আরও বিশদ সরবরাহ করতে পারবেন?
উইলসন

1
@ উইলসন - আমি নিশ্চিত এটিতে প্রচুর জেএমপি জড়িত।
হুড্যাটিকাস

উত্তর:


649

প্রান্তিককরণের সীমাবদ্ধতাগুলি পূরণ করতে প্যাডিং যুক্ত হওয়ার কারণে এটি। ডেটা স্ট্রাকচার সারিবদ্ধকরণ কর্মক্ষমতা এবং প্রোগ্রামের যথার্থতা উভয়কেই প্রভাবিত করে:

  • ভুল সংযুক্ত অ্যাক্সেস একটি হার্ড ত্রুটি হতে পারে (প্রায়শই SIGBUS)।
  • ভুল সংযুক্ত অ্যাক্সেস একটি নরম ত্রুটি হতে পারে।
    • হয় হার্ডওয়্যারে সংশোধন করা হয়েছে, একটি পরিমিত পারফরম্যান্স-অবক্ষয়ের জন্য।
    • বা সফটওয়্যারটিতে এমুলেশন দ্বারা সংশোধন করা হয়েছে, একটি তীব্র কর্মক্ষমতা-অবক্ষয়ের জন্য।
    • এছাড়াও, পারমাণবিকতা এবং অন্যান্য সম্মতি-গ্যারান্টিগুলি ভেঙে যেতে পারে, যার ফলে সূক্ষ্ম ত্রুটি হয়।

এখানে একটি x86 প্রসেসরের জন্য আদর্শ সেটিংস ব্যবহারের উদাহরণ রয়েছে (সমস্ত ব্যবহৃত 32 এবং 64 বিট মোড):

struct X
{
    short s; /* 2 bytes */
             /* 2 padding bytes */
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 3 padding bytes */
};

struct Y
{
    int   i; /* 4 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
    short s; /* 2 bytes */
};

struct Z
{
    int   i; /* 4 bytes */
    short s; /* 2 bytes */
    char  c; /* 1 byte */
             /* 1 padding byte */
};

const int sizeX = sizeof(struct X); /* = 12 */
const int sizeY = sizeof(struct Y); /* = 8 */
const int sizeZ = sizeof(struct Z); /* = 8 */

বিন্যাসের মাধ্যমে সদস্যদের বাছাই করে কাঠামোর আকার হ্রাস করা যায় (আকারের অনুসারে বাছাই করা মূল ধরণের ক্ষেত্রে এটি যথেষ্ট) ( Zউপরের উদাহরণে কাঠামোর মতো )।

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


38
আমি এখানে একটি নোট রাখতে চাই: বেশিরভাগ প্রসেসর আপনাকে স্বাক্ষরবিহীন মেমরি অ্যাক্সেসের জন্য শাস্তি দেয় (যেমন আপনি উল্লেখ করেছেন), তবে আপনি এটি ভুলতে পারবেন না যে অনেকে একে সম্পূর্ণরূপে এড়িয়ে যান। বেশিরভাগ এমআইপিএস চিপস, বিশেষত, একটি স্বাক্ষরবিহীন অ্যাক্সেসের ক্ষেত্রে ব্যতিক্রম ছুঁড়ে দেবে।
কোডি ব্রোসিওস

35
X86 চিপগুলি প্রকৃতপক্ষে তুলনায় অনন্য that যে তারা দণ্ডযুক্ত হয়েও নিযুক্ত স্বাক্ষরিত অ্যাক্সেসের অনুমতি দেয়; আফাইক অধিকাংশ চিপস ব্যতিক্রম ছুঁড়ে ফেলবে, কেবল কয়েকটি নয়। পাওয়ারপিসি আরেকটি সাধারণ উদাহরণ।
অন্ধকার শিকারি

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

5
@ ডার্ক - সম্পূর্ণ সম্মত তবে বেশিরভাগ ডেস্কটপ প্রসেসরগুলি x86 / x64 হয়, তাই বেশিরভাগ চিপগুলি ডেটা প্রান্তিককরণ ত্রুটি দেয় না;)
অ্যারন

27
স্বাক্ষরবিহীন ডেটা অ্যাক্সেস সাধারণত সিআইএসসি আর্কিটেকচারে পাওয়া একটি বৈশিষ্ট্য এবং বেশিরভাগ আরআইএসসি আর্কিটেকচার এটিকে অন্তর্ভুক্ত করে না (এআরএম, এমআইপিএস, পাওয়ারপিসি, সেল)। প্রকৃতপক্ষে, বেশিরভাগ চিপগুলি ডেস্কটপ প্রসেসর নয়, সংখ্যার চিপ দ্বারা এম্বেড করা নিয়মের জন্য এবং এর বেশিরভাগ অংশই হ'ল RISC আর্কিটেকচার।
লারা ডগান

191

প্যাকিং এবং বাইট প্রান্তিককরণ, এখানে সিএফএকিউতে বর্ণিত :

এটা সারিবদ্ধ করার জন্য। অনেক প্রসেসর 2- এবং 4-বাইট পরিমাণে (যেমন ints এবং দীর্ঘ ints) অ্যাক্সেস করতে পারবেন না যদি তারা প্রতিটি উপায়ে ক্র্যাড হয়।

ধরুন আপনার এই কাঠামো রয়েছে:

struct {
    char a[3];
    short int b;
    long int c;
    char d[3];
};

এখন, আপনি ভাবতে পারেন যে এই কাঠামোর স্মৃতিতে এই জাতীয় প্যাক করা সম্ভব হওয়া উচিত:

+-------+-------+-------+-------+
|           a           |   b   |
+-------+-------+-------+-------+
|   b   |           c           |
+-------+-------+-------+-------+
|   c   |           d           |
+-------+-------+-------+-------+

তবে এটি প্রসেসরের উপর আরও অনেক সহজ, যদি সংকলক এটিকে এইভাবে সাজায়:

+-------+-------+-------+
|           a           |
+-------+-------+-------+
|       b       |
+-------+-------+-------+-------+
|               c               |
+-------+-------+-------+-------+
|           d           |
+-------+-------+-------+

বস্তাবন্দী সংস্করণে লক্ষ্য করুন যে আপনার এবং আমার পক্ষে খ এবং সি ক্ষেত্রগুলি কীভাবে মোড়ানো রয়েছে তা দেখতে আপনার পক্ষে কমপক্ষে খানিকটা কঠিন? সংক্ষেপে, এটি প্রসেসরের পক্ষেও শক্ত। অতএব, বেশিরভাগ সংকলকগুলি কাঠামোটি (যেমন অতিরিক্ত, অদৃশ্য ক্ষেত্রগুলি সহ) প্যাড করবে:

+-------+-------+-------+-------+
|           a           | pad1  |
+-------+-------+-------+-------+
|       b       |     pad2      |
+-------+-------+-------+-------+
|               c               |
+-------+-------+-------+-------+
|           d           | pad3  |
+-------+-------+-------+-------+

1
এখন মেমরি স্লট প্যাড 1, প্যাড 2 এবং প্যাড 3 এর ব্যবহার কী।
লক্ষ্মী শ্রীকান্ত চিতলা


@ এমএমএফ এটি ভুল হতে পারে তবে আমি এটি বেশিরভাগভাবে পাই না: অ্যারেগুলিতে পয়েন্টারের জন্য কেন কোনও মেমরির স্লট নেই?
বালাজ বার্কাস্ক

1
@ BalázsBörcsök এগুলি ধ্রুব আকারের অ্যারেগুলি হয় এবং তাই তাদের উপাদানগুলি স্থির অফসেটগুলিতে সরাসরি স্ট্রাক্টে সংরক্ষণ করা হয়। সংকলক সংকলনের সময় এই সমস্ত জানে তাই পয়েন্টারটি অন্তর্ভুক্ত। উদাহরণস্বরূপ, যদি আপনার কাছে এই ধরণের স্ট্রাক্ট ভেরিয়েবল থাকে এবং sতারপরে (উত্তরে দেখানো প্রান্তিককরণ দেওয়া থাকে)। পয়েন্টারটি কেবল তখনই সংরক্ষণ করা হয় যদি অ্যারেগুলির একটি পরিবর্তনশীল আকার থাকে (যেমন, পরিবর্তে ঘোষিত হয়েছিল ) তবে তারপরে উপাদানগুলি অন্য কোথাও সংরক্ষণ করতে হবে। &s.a == &s&s.d == &s + 12achar a[]char a[3]
kbolino

27

আপনি যদি উদাহরণস্বরূপ ব্যবহারের জন্য জিসিসির সাথে কাঠামোর একটি নির্দিষ্ট আকার রাখতে চান __attribute__((packed))

উইন্ডোজে আপনি / জেডপি বিকল্পের সাথে ক্লি.এক্স.কম সংযোগকারী ব্যবহার করার সময় এক বাইটে প্রান্তিককরণ সেট করতে পারেন ।

সাধারণত সিপিইউর ডেটা অ্যাক্সেস করা সহজ যা 4 (বা 8) এর একাধিক, প্ল্যাটফর্ম এবং সংকলক নির্ভর করে।

সুতরাং এটি মূলত প্রান্তিককরণের বিষয়।

এটি পরিবর্তন করার জন্য আপনার ভাল কারণ থাকতে হবে।


5
"ভাল কারণগুলির" উদাহরণ: আগামীকাল প্রদর্শিত হচ্ছে-প্রমাণীকরণের ডেমো কোডের একটি জটিল কাঠামোর জন্য 32-বিট এবং 64-বিট সিস্টেমের মধ্যে বাইনারি সামঞ্জস্যতা (প্যাডিং) সামঞ্জস্য রেখে। অনেক সময় প্রয়োজনকে স্বচ্ছতার চেয়ে অগ্রাধিকার নিতে হয়।
মিঃআর

2
অপারেটিং সিস্টেমের উল্লেখ না করে সবকিছু ঠিক আছে। এটি সিপিইউ গতির জন্য সমস্যা, ওএস মোটেই জড়িত নয়।
ব্লেসরব্লেড

3
আর একটি ভাল কারণ হ'ল যদি আপনি কোনও স্ট্রাক্টে একটি ডাস্টাস্ট্রিম স্টাফ করে থাকেন, যেমন নেটওয়ার্ক প্রোটোকল পার্স করার সময়।
ceo

1
@ ডলম্যান আমি কেবল উল্লেখ করেছি যে "অপেরাটিন সিস্টেমের পক্ষে ডেটা অ্যাক্সেস করা সহজ" ভুল, কারণ ওএস ডেটা অ্যাক্সেস করে না।
ব্লেজারব্লেড

1
@ ডলম্যান বাস্তবে, এবিআই (অ্যাপ্লিকেশন বাইনারি ইন্টারফেস) সম্পর্কে আপনার কথা বলা উচিত। ডিফল্ট প্রান্তিককরণ (আপনি যদি উত্সটিতে এটি পরিবর্তন না করেন তবে ব্যবহৃত হয়) এটিবিআইয়ের উপর নির্ভর করে এবং অনেক ওএস একাধিক এবিআইকে সমর্থন করে (বলুন, 32- এবং 64-বিট, বা বিভিন্ন ওএস থেকে বাইনারিগুলির জন্য, বা সংকলনের বিভিন্ন উপায়ে একই ওএসের জন্য একই বাইনারি)। OTOH, পারফরম্যান্স অনুযায়ী সুবিধাজনক কি সিপিইউর উপর নির্ভর করে - আপনি 32 বা 64 বিট মোড ব্যবহার করেন কিনা তা মেমরির একইভাবে অ্যাক্সেস করা হয় (আমি রিয়েল মোডে মন্তব্য করতে পারি না, তবে আজকাল পারফরম্যান্সের জন্য খুব কমই প্রাসঙ্গিক বলে মনে হচ্ছে)। আইআইআরসি পেন্টিয়াম 8-বাইট প্রান্তিককরণ পছন্দ করে।
ব্লেজারব্লেড

15

এটি বাইট সারিবদ্ধকরণ এবং প্যাডিংয়ের কারণে হতে পারে যাতে আপনার প্ল্যাটফর্মের কাঠামোটি এমনকি একাধিক বাইট (বা শব্দ) বেরিয়ে আসে। উদাহরণস্বরূপ লিনাক্সে সি-তে নিম্নলিখিত 3 কাঠামো:

#include "stdio.h"


struct oneInt {
  int x;
};

struct twoInts {
  int x;
  int y;
};

struct someBits {
  int x:2;
  int y:6;
};


int main (int argc, char** argv) {
  printf("oneInt=%zu\n",sizeof(struct oneInt));
  printf("twoInts=%zu\n",sizeof(struct twoInts));
  printf("someBits=%zu\n",sizeof(struct someBits));
  return 0;
}

বাইটস এর মাপের সদস্যদের যথাক্রমে 4 বাইট (32 বিট), 8 বাইট (2x 32 বিট) এবং 1 বাইট (2 + 6 বিট) হয় উপরের প্রোগ্রামটি (জিসিসি ব্যবহার করে লিনাক্সে) 4, 8 এবং 4 হিসাবে আকারগুলি মুদ্রণ করে - যেখানে শেষ কাঠামোটি প্যাডযুক্ত যাতে এটি একটি একক শব্দ (আমার 32 বিট প্ল্যাটফর্মে 4 x 8 বিট বাইট) থাকে।

oneInt=4
twoInts=8
someBits=4

4
"জিসিসি ব্যবহার করে লিনাক্সে সি" আপনার প্ল্যাটফর্মটি বর্ণনা করার জন্য যথেষ্ট নয়। প্রান্তিককরণ বেশিরভাগ সিপিইউ আর্কিটেকচারের উপর নির্ভর করে।
ডলমেন

- @ কাইল বার্টন মাফ করবেন, কাঠামো "কিছু বিটস" এর আকার 4 এর সমান কেন আমি বুঝতে পারি না, আমি 8 বাইট প্রত্যাশা করি যেহেতু এখানে 2 পূর্ণসংখ্যা ঘোষিত (2 * আকারের (ইনট)) = 8 বাইট রয়েছে। ধন্যবাদ
youpilat13

1
হাই @ youpilat13, :2এবং :6আসলে 2 এবং 6 বিট নির্দিষ্ট করছে, এক্ষেত্রে 32 বিট পূর্ণ পূর্ণসংখ্যার নয়। someBits.x, মাত্র 2 বিট হ'ল কেবল 4 সম্ভাব্য মান সংরক্ষণ করতে পারে: 00, 01, 10 এবং 11 (1, 2, 3 এবং 4)। এটা কোনো কিছু হলো? বৈশিষ্ট্য সম্পর্কে এখানে একটি নিবন্ধটি দেওয়া হয়েছে: geeksforgeeks.org/bit-fields-c
কাইল বার্টন

11

আরো দেখুন:

মাইক্রোসফ্ট ভিজ্যুয়াল সি এর জন্য:

http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx

এবং জিসিসি মাইক্রোসফ্টের সংকলকটির সাথে সামঞ্জস্যতার দাবি করেছে:

http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html

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

আমি বেশ নিশ্চিত সদস্য-অর্ডার করা হয় সি নিশ্চিত , কিন্তু আমি এটি গণনা না, যখন একটি ক্রস-প্ল্যাটফর্ম বা ক্রস কম্পাইলার প্রোগ্রাম লেখা।


4
"আমি নিশ্চিত যে মেম্বার-অর্ডার সিতে গ্রান্ট হয়েছে"। হ্যাঁ, সি 99 বলেছেন: "কাঠামোগত কোনও অবজেক্টের মধ্যে, বিট-ফিল্ডের নন-বিট-ফিল্ড সদস্য এবং যে ইউনিটগুলিতে বিট-ফিল্ডগুলি থাকে সেগুলির ঠিকানা রয়েছে যা তারা ঘোষিত হওয়ার ক্রমটিতে বৃদ্ধি পায়।" এ আরো মান ধার্মিকতা: stackoverflow.com/a/37032302/895245
সিরো Santilli冠状病毒审查六四事件法轮功


8

কোনও কাঠামোর আকার তার অংশগুলির যোগফলের চেয়ে বড় যা প্যাকিং বলে। একটি নির্দিষ্ট প্রসেসরের একটি পছন্দসই ডেটা আকার থাকে যা এটি দিয়ে কাজ করে। 32-বিট (4 বাইট) যদি সর্বাধিক আধুনিক প্রসেসরের পছন্দসই আকার। যখন এই ধরণের সীমানায় ডেটা থাকে তখন মেমোরি অ্যাক্সেস করা সেই আকারের সীমানাকে অবিচ্ছিন্ন করে তোলে এমন জিনিসগুলির চেয়ে বেশি দক্ষ।

উদাহরণ স্বরূপ. সাধারণ কাঠামো বিবেচনা করুন:

struct myStruct
{
   int a;
   char b;
   int c;
} data;

যদি মেশিনটি 32-বিট মেশিন হয় এবং ডেটা 32-বিট সীমানায় সংযুক্ত থাকে, আমরা একটি তাত্ক্ষণিক সমস্যা দেখতে পাই (কোনও কাঠামোর সারিবদ্ধতা ধরে না রেখে)। এই উদাহরণে, আসুন আমরা ধরে নিই যে কাঠামোর ডেটা 1024 ঠিকানায় শুরু হয় (0x400 - নোট করুন যে সর্বনিম্ন 2 বিট শূন্য, সুতরাং ডেটাটি 32-বিট সীমানায় সংযুক্ত করা হয়)। ডেটা.এ অ্যাক্সেস সূক্ষ্মভাবে কাজ করবে কারণ এটি একটি সীমানা - 0x400 এ শুরু হয়। ডেটা.বিতে অ্যাক্সেসও ঠিকঠাক কাজ করবে, কারণ এটি 0x404 ঠিকানায় রয়েছে - অন্য 32-বিট সীমানা। তবে একটি স্বাক্ষরবিহীন কাঠামো 0x405 ঠিকানায় ডেটা। ডেটা। এর 4 বাইট 0x405, 0x406, 0x407, 0x408 এ রয়েছে। একটি 32-বিট মেশিনে, সিস্টেমটি একটি মেমরি চক্র চলাকালীন ডেটা.c পড়ত তবে 4 টি বাইটের মধ্যে কেবল 3 পায় (চতুর্থ বাইটটি পরবর্তী সীমানায় থাকে)। সুতরাং, 4 র্থ বাইট পেতে সিস্টেমকে একটি দ্বিতীয় মেমরি অ্যাক্সেস করতে হবে,

এখন, যদি 0x405 ঠিকানায় ডেটা। কোড স্থাপনের পরিবর্তে, সংকলকটি কাঠামোটি 3 বাইট দ্বারা প্যাড করে এবং ডাটা কোড.এক্স 0x408 ঠিকানায় রাখে, তবে তথ্যটি পড়ার জন্য সিস্টেমটি কেবলমাত্র 1 টি চক্রের প্রয়োজন হবে, সেই তথ্য উপাদানটিতে অ্যাক্সেসের সময় কাটাতে হবে 50% দ্বারা প্যাডিং প্রক্রিয়াজাতকরণ দক্ষতার জন্য মেমরি দক্ষতা অদলবদল করে। কম্পিউটারগুলিতে প্রচুর পরিমাণে মেমরি থাকতে পারে (বহু গিগাবাইট), সংকলকরা মনে করেন যে অদলবদল (গতির চেয়ে বেশি গতি) একটি যুক্তিসঙ্গত।

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

অন্যদিকে, বিভিন্ন সংকলকগুলির ডেটা স্ট্রাকচার প্যাকিং পরিচালনা করার জন্য বিভিন্ন ক্ষমতা রয়েছে। উদাহরণস্বরূপ, ভিজ্যুয়াল সি / সি ++ এ সংকলক # প্রগমা প্যাক কমান্ড সমর্থন করে। এটি আপনাকে ডেটা প্যাকিং এবং প্রান্তিককরণ সামঞ্জস্য করতে অনুমতি দেবে।

উদাহরণ স্বরূপ:

#pragma pack 1
struct MyStruct
{
    int a;
    char b;
    int c;
    short d;
} myData;

I = sizeof(myData);

আমার এখন ১১ এর দৈর্ঘ্য হওয়া উচিত the প্রগমা ব্যতীত, আমি সংকলকের ডিফল্ট প্যাকিংয়ের উপর নির্ভর করে 11 থেকে 14 (এবং কিছু সিস্টেমে, তত 32 হিসাবে) হতে পারি।


এটি কাঠামো প্যাডিংয়ের পরিণতিগুলি নিয়ে আলোচনা করে তবে এটি প্রশ্নের উত্তর দেয় না।
কিথ থম্পসন

" ... প্যাকিং বলা হয় বলেই ... ... আমার মনে হয় আপনি" প্যাডিং "বলতে চাইছেন।" বেশিরভাগ আধুনিক প্রসেসরের পছন্দনীয় আকার যদি 32-বিট (4 বাইট) হয় "- এটি কিছুটা ওভারসিম্প্লিফিকেশন। সাধারণত 8, 16, 32, এবং 64 বিট সমর্থিত মাপ; প্রায়ই একে আকার নিজস্ব প্রান্তিককরণ হয়েছে এবং আমি নিশ্চিত আপনার উত্তর কোনো নতুন তথ্য গৃহীত উত্তরে ইতিমধ্যে নয় যোগ
কিথ থম্পসন

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

এই প্রসঙ্গে "প্যাকিং" সাধারণত ডিফল্টের চেয়ে সদস্যদের আরও বেশি শক্তভাবে বরাদ্দকে বোঝায় #pragma pack। সদস্যদের তাদের ডিফল্ট প্রান্তিককরণ বরাদ্দ হয়, আমি সাধারণত বলতে চাই কাঠামো না বস্তাবন্দী।
কিথ থম্পসন

প্যাকিং একটি ওভারলোডেড টার্মের মতো। এর অর্থ আপনি কীভাবে কাঠামোগত উপাদানগুলিকে মেমরিতে রাখেন। একটি বাক্সে জিনিস রাখার অর্থের সাথে মিলিত (চলার জন্য প্যাকিং)। এর অর্থ হল কোনও প্যাডিং ছাড়াই উপাদানগুলিকে মেমোরিতে রাখা ("শক্তভাবে প্যাক করা" এর জন্য একটি ছোট হাতের সাজানো)। তারপরে # প্রাগমা প্যাক কমান্ডে শব্দের কমান্ড সংস্করণ রয়েছে।
sid1138

5

যদি আপনি স্পষ্টভাবে বা স্পষ্টভাবে স্ট্রাক্টের সারিবদ্ধতা সেট করে থাকেন তবে এটি এটি করতে পারে। ৪ টি সারিবদ্ধ একটি স্ট্রাক্ট সর্বদা 4 বাইটের একাধিক হবে এমনকি তার সদস্যদের আকার এমন কিছু হবে যা 4 বাইটের একাধিক নয়।

এছাড়াও একটি লাইব্রেরি x86 এর অধীনে 32-বিট ইনট সহ সংকলিত হতে পারে এবং আপনি যদি 64-বিট প্রসেসের সাথে এর উপাদানগুলির তুলনা করছেন তবে আপনি যদি হাতের সাহায্যে এটি করছিলেন তবে আপনাকে আলাদা ফলাফল দেবে।


5

C99 N1256 স্ট্যান্ডার্ড খসড়া

http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf

6.5.3.4 আকার অপারেটর :

3 যখন কাঠামো বা ইউনিয়নের ধরণের কোনও অপরেন্ডে প্রয়োগ করা হয়, ফলাফলটি অভ্যন্তরীণ এবং ট্রেলিং প্যাডিং সহ এমন কোনও সামগ্রীর মোট বাইটের সংখ্যা।

7.7.২.১ কাঠামো এবং ইউনিয়ন নির্দিষ্টকরণকারী :

13 ... স্ট্রাকচার অবজেক্টের মধ্যে নামবিহীন প্যাডিং থাকতে পারে, তবে এটির শুরুতে নয়।

এবং:

15 কোনও কাঠামো বা ইউনিয়নের শেষে নামবিহীন প্যাডিং থাকতে পারে।

নতুন C99 নমনীয় অ্যারে সদস্য বৈশিষ্ট্য ( struct S {int is[];};) প্যাডিংগুলিকেও প্রভাবিত করতে পারে:

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

সংযুক্ত জে বহনযোগ্য বিষয়গুলির পুনরাবৃত্তি:

নিম্নলিখিতগুলি অনির্ধারিত: ...

  • কাঠামো বা ইউনিয়নে মান সংরক্ষণ করার সময় প্যাডিং বাইটের মান (.2.২..1.১)

সি ++ 11 এন 3337 স্ট্যান্ডার্ড খসড়া

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

5.3.3 মাপ :

2 যখন কোনও ক্লাসে প্রয়োগ করা হয়, ফলাফল হ'ল শ্রেণীর কোনও অবজেক্টে বাইটের সংখ্যা সহ সেই ধরণের অবজেক্টগুলিকে অ্যারে রাখার জন্য প্রয়োজনীয় কোনও প্যাডিং।

৯.২ শ্রেণির সদস্য :

একটি স্ট্যান্ডার্ড-লেআউট স্ট্রাক্ট অবজেক্টের একটি পয়েন্টার, একটি পুনরায় ব্যাখ্যা-কাস্টম ব্যবহার করে উপযুক্ত রূপান্তরিত করে, এর প্রাথমিক সদস্যকে নির্দেশ করে (অথবা যদি সেই সদস্যটি বিট-ফিল্ড হয়, তবে এটি যে ইউনিটে থাকে সেখানে) এবং তদ্বিপরীত। [দ্রষ্টব্য: সুতরাং একটি মান-লেআউট স্ট্রাক্ট অবজেক্টের মধ্যে নামবিহীন প্যাডিং থাকতে পারে তবে উপযুক্ত প্রান্তিককরণ অর্জনের জন্য প্রয়োজনীয় হিসাবে এটি শুরুতে নয়। - শেষ নোট]

আমি কেবল নোটটি বুঝতে যথেষ্ট সি ++ জানি :-)


4

অন্যান্য উত্তরের পাশাপাশি, একটি স্ট্রাক্টের ভার্চুয়াল ফাংশন থাকতে পারে (তবে সাধারণত থাকে না), সেক্ষেত্রে স্ট্রাক্টের আকারটিও ভিটিবিএলের স্থান অন্তর্ভুক্ত করবে।


8
বেশ না। সাধারণ বাস্তবায়নে, কাঠামোর সাথে যা যুক্ত করা হয় তা হ'ল একটি ভিটিবেল পয়েন্টার
ডন ওয়েকফিল্ড

3

সি ভাষা স্মৃতিতে কাঠামোগত উপাদানগুলির অবস্থান সম্পর্কে কিছু স্বাধীনতা সংকলন করে:

  • মেমরির গর্তগুলি যে কোনও দুটি উপাদানগুলির মধ্যে উপস্থিত হতে পারে এবং শেষ উপাদানটির পরে। লক্ষ্য কম্পিউটারে নির্দিষ্ট ধরণের অবজেক্টগুলিকে সম্বোধনের সীমানা দ্বারা সীমাবদ্ধ করা যেতে পারে
  • আকারের অপারেটরের ফলাফলের সাথে "মেমরি হোলস" আকার অন্তর্ভুক্ত। আকারে কেবল নমনীয় অ্যারে আকার অন্তর্ভুক্ত করা হয় না, যা সি / সি ++ এ উপলব্ধ
  • ভাষার কিছু প্রয়োগ আপনাকে প্রগমা এবং সংকলক বিকল্পগুলির মাধ্যমে কাঠামোর মেমরি লেআউট নিয়ন্ত্রণ করতে দেয়

সি ভাষা কাঠামোর উপাদানগুলির বিন্যাসের প্রোগ্রামারকে কিছু নিশ্চয়তা প্রদান করে:

  • সংকলকগুলির মেমরি ঠিকানাগুলি বাড়ানোর উপাদানগুলির ক্রম নির্ধারণের জন্য প্রয়োজনীয়
  • প্রথম উপাদানটির ঠিকানা কাঠামোর সূচনা ঠিকানার সাথে মিলে যায়
  • নামবিহীন বিট ক্ষেত্রগুলি সংলগ্ন উপাদানগুলির প্রয়োজনীয় ঠিকানা প্রান্তিককরণের কাঠামোর মধ্যে অন্তর্ভুক্ত থাকতে পারে

উপাদানগুলির সারিবদ্ধকরণ সম্পর্কিত সমস্যাগুলি:

  • বিভিন্ন কম্পিউটার বস্তুর প্রান্তকে বিভিন্ন উপায়ে লাইন করে
  • বিট ক্ষেত্রের প্রস্থে বিভিন্ন বিধিনিষেধ
  • কোনও শব্দে বাইটগুলি কীভাবে সংরক্ষণ করতে হবে তার বিষয়ে কম্পিউটারের মধ্যে পার্থক্য রয়েছে (ইন্টেল ৮০x86 and এবং মটোরোলা 68৮০০০)

সারিবদ্ধকরণ কীভাবে কাজ করে:

  • কাঠামোর দ্বারা দখলকৃত ভলিউমকে এই জাতীয় কাঠামোর অ্যারের প্রান্তিক একক উপাদানের আকার হিসাবে গণনা করা হয়। কাঠামোটি শেষ হওয়া উচিত যাতে পরবর্তী নিম্নলিখিত কাঠামোর প্রথম উপাদানটি প্রান্তিককরণের প্রয়োজনীয়তা লঙ্ঘন করে না

পিএস আরও বিশদ তথ্য এখানে পাওয়া যায়: "স্যামুয়েল পি। হার্বিসন, গাই এল। স্টিল সিএ রেফারেন্স, (5.6.2 - 5.6.7)"


2

ধারণাটি হ'ল গতি এবং ক্যাশে বিবেচনার জন্য অপারেশনগুলি তাদের প্রাকৃতিক আকারের সাথে সংযুক্ত ঠিকানাগুলি থেকে পড়া উচিত। এটি ঘটতে, সংকলক প্যাডগুলি কাঠামোর সদস্যগণ যাতে নীচের সদস্য বা নীচের কাঠামোটি সারিবদ্ধ করা হবে।

struct pixel {
    unsigned char red;   // 0
    unsigned char green; // 1
    unsigned int alpha;  // 4 (gotta skip to an aligned offset)
    unsigned char blue;  // 8 (then skip 9 10 11)
};

// next offset: 12

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

কিছু আর্কিটেকচারকে প্রকৃতপক্ষে বিভ্রান্তিযুক্ত পড়া এবং লেখাগুলি এবং এআরএম আর্কিটেকচারের প্রাথমিক সংস্করণগুলি (যা আজকের সমস্ত মোবাইল সিপিইউতে বিবর্তিত হয়েছিল) আটকে আছে ... ভাল, তারা আসলে সেইগুলির জন্য খারাপ ডেটা ফিরিয়ে দিয়েছে। (তারা নিম্ন-অর্ডার বিট উপেক্ষা করেছে।)

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

টিএল; ডিআর: প্রান্তিককরণ গুরুত্বপূর্ণ।

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