ความหมายของ "__attribute __ ((บรรจุ, จัดชิด (4)))" คืออะไร


122

เป็นภาษาซีเขียนว่า:

typedef struct __attribute__((packed, aligned(4))) Ball {
    float2 delta;
    float2 position;
    //float3 color;
    float size;
    //int arcID;
    //float arcStr;
} Ball_t;
Ball_t *balls;

กรุณาบอกความหมายของมันและจะใช้คีย์เวิร์ดนี้อย่างไร


4
มันเป็น"แอตทริบิวต์ประเภท" .. (ฉันพบสิ่งนี้พร้อมกับ "แอตทริบิวต์ C ที่บรรจุ" ใน Google อย่างน้อยคนอื่นก็ทำได้ดีเช่นกัน!)

1
ดูคำถามนี้ - แม้ว่าaligned(4)คุณอาจไม่ต้องกังวลมากนัก
Keith Thompson

คำตอบ:


157

ก่อนที่จะตอบฉันต้องการให้ข้อมูลบางส่วนจาก Wiki


การจัดตำแหน่งโครงสร้างข้อมูลเป็นวิธีการจัดเรียงและเข้าถึงข้อมูลในหน่วยความจำคอมพิวเตอร์ ประกอบด้วยสองแยกประเด็น แต่ที่เกี่ยวข้องกับการจัดเรียงข้อมูลและโครงสร้างข้อมูล padding

เมื่อคอมพิวเตอร์สมัยใหม่อ่านหรือเขียนไปยังที่อยู่หน่วยความจำคอมพิวเตอร์จะทำสิ่งนี้เป็นชิ้นขนาดคำ (เช่นชิ้นส่วนขนาด 4 ไบต์ในระบบ 32 บิต) การจัดแนวข้อมูลหมายถึงการวางข้อมูลที่ออฟเซ็ตหน่วยความจำเท่ากับผลคูณของขนาดคำซึ่งจะเพิ่มประสิทธิภาพของระบบเนื่องจากวิธีที่ CPU จัดการกับหน่วยความจำ

เพื่อให้สอดคล้องข้อมูลก็อาจจะจำเป็นต้องใส่ไบต์ความหมายบางอย่างระหว่างการสิ้นสุดของโครงสร้างข้อมูลล่าสุดและการเริ่มต้นของการต่อไปซึ่งเป็นโครงสร้างข้อมูล padding


gcc มีฟังก์ชันในการปิดการใช้งานช่องว่างภายในโครงสร้าง คือหลีกเลี่ยงไบต์ที่ไร้ความหมายเหล่านี้ในบางกรณี พิจารณาโครงสร้างต่อไปนี้:

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}sSampleStruct;

sizeof(sSampleStruct)จะเป็น 12 แทนที่จะเป็น 8 เนื่องจากโครงสร้างภายใน ตามค่าเริ่มต้นใน X86 โครงสร้างจะได้รับการจัดตำแหน่ง 4 ไบต์:

typedef struct
{
     char Data1;
     //3-Bytes Added here.
     int Data2;
     unsigned short Data3;
     char Data4;
     //1-byte Added here.

}sSampleStruct;

เราสามารถใช้__attribute__((packed, aligned(X)))เพื่อยืนยันช่องว่างขนาด (X) โดยเฉพาะ X ควรเป็นกำลังสอง อ้างอิงที่นี่

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}__attribute__((packed, aligned(1))) sSampleStruct;  

ดังนั้นแอตทริบิวต์ gcc ที่ระบุข้างต้นจึงไม่อนุญาตให้มีการเว้นโครงสร้าง ดังนั้นขนาดจะเป็น 8 ไบต์

หากคุณต้องการทำเช่นเดียวกันสำหรับโครงสร้างทั้งหมดเพียงแค่เราสามารถผลักดันค่าการจัดตำแหน่งให้ซ้อนกันโดยใช้ #pragma

#pragma pack(push, 1)

//Structure 1
......

//Structure 2
......

#pragma pack(pop)

6
หากหน่วยความจำเก็บข้อมูลเป็นชิ้น 4 ไบต์เหตุใดจึงไม่เพิ่ม 2 ไบต์ช่องว่างในช่องว่างที่ไม่ได้ลงชื่อ (ยาว 2 ไบต์) หรือคอมไพเลอร์เพียงเพิ่มไบต์ช่องว่างภายในให้กับสมาชิกตัวที่ 1 และสุดท้ายของโครงสร้าง? คุณช่วยชี้แจงได้ไหม
ผู้ใช้

5
@ ผู้ใช้กรุณาอ้างถึงสิ่งนี้ด้วย ถ้ายังไม่กระจ่างกรุณามาขอความช่วยเหลือstackoverflow.com/questions/11772553/…
Jeyaram

ใครบอกว่าไบต์ช่องว่างเหล่านี้ไม่มีความหมายก็ไม่รู้ว่าการเข้าถึงข้อมูลที่ไม่ตรงแนวนั้นเป็นความแปลกของสถาปัตยกรรม x86 ไบต์เหล่านี้จำเป็นเพื่อหลีกเลี่ยงข้อยกเว้นเมื่อโปรเซสเซอร์พยายามโหลดเช่นจำนวนเต็ม - ข้อมูลที่คร่อมขอบเขตการจัดตำแหน่งตามธรรมชาติ
Tanveer Badar

86
  • packedหมายความว่ามันจะใช้พื้นที่ที่เล็กที่สุดเท่าที่จะเป็นไปได้struct Ballนั่นคือมันจะอัดฟิลด์เข้าด้วยกันโดยไม่ต้องเว้นช่องว่าง
  • alignedหมายความว่าแต่ละรายการstruct Ballจะเริ่มต้นในขอบเขต 4 ไบต์กล่าวคือstruct Ballที่อยู่สามารถหารด้วย 4

นี่คือส่วนขยาย GCC ไม่ใช่ส่วนหนึ่งของมาตรฐาน C ใด ๆ


17

แอตทริบิวต์packedหมายความว่าคอมไพเลอร์จะไม่เพิ่มช่องว่างระหว่างฟิลด์ของstruct. โดยปกติช่องว่างภายในจะใช้เพื่อทำให้ช่องมีขนาดตามธรรมชาติเนื่องจากสถาปัตยกรรมบางแห่งกำหนดบทลงโทษสำหรับการเข้าถึงที่ไม่ตรงแนวหรือไม่อนุญาตเลย

aligned(4) หมายความว่าโครงสร้างควรจัดชิดกับที่อยู่ที่หารด้วย 4 ได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.