Struct padding ve alignment nedir? __attribute__((packed)) ne zaman kullanılmalı, riskleri nelerdir?

Cevap

İşlemciler veriye doğal hizalamasında (4 byte'lık uint32_t için 4'ün katı adres) en verimli erişir. Derleyici bu yüzden struct alanları arasına padding byte'ları ekler. Struct'ın toplam boyutu da en büyük üyenin hizalamasının katına yuvarlanır.

struct A {          /* offset */
    uint8_t  a;     /* 0, sonra 3 byte padding */
    uint32_t b;     /* 4 */
    uint16_t c;     /* 8, sonra 2 byte padding */
};                  /* sizeof = 12 */

struct B {          /* aynı alanlar, büyükten küçüğe */
    uint32_t b;     /* 0 */
    uint16_t c;     /* 4 */
    uint8_t  a;     /* 6, sonra 1 byte padding */
};                  /* sizeof = 8 */

Alanları büyükten küçüğe sıralamak padding'i en aza indirir ve RAM kazandırır.

packed

typedef struct __attribute__((packed)) {
    uint8_t  cmd;
    uint32_t value;
    uint16_t crc;
} frame_t;          /* sizeof = 7 */

Kullanım yerleri: haberleşme protokol çerçeveleri, dosya formatları, donanıma birebir uyması gereken yapılar.

Riskler

  • Hizalanmamış erişim: Cortex-M0/M0+ hizalanmamış LDR ile HardFault verir. Cortex-M3/M4 destekler ama daha yavaştır. Derleyici packed alana doğrudan erişirken güvenli kod üretir, ama alanın adresi bir uint32_t * pointer'a alınırsa bu garanti kaybolur.
  • Performans: Byte byte okuma kodu üretilir.
  • Taşınabilirlik: Endianness hâlâ çözülmez; farklı mimaride byte sırası değişir.

Daha güvenli alternatif

Protokol verisini struct'a cast etmek yerine açıkça serialize etmek:

buf[0] = f->cmd;
buf[1] = (uint8_t)(f->value);
buf[2] = (uint8_t)(f->value >> 8);
buf[3] = (uint8_t)(f->value >> 16);
buf[4] = (uint8_t)(f->value >> 24);   /* little-endian, açık ve taşınabilir */

Boyutu derleme zamanında doğrulamak için: _Static_assert(sizeof(frame_t) == 7, "frame size");

  1. C dilinde volatile anahtar kelimesi ne işe yarar?OrtaC ProgramlamaEmbedded
  2. Bir yazmaçtaki belirli bir biti set, clear ve toggle eden C kodunu yazın.KolayC ProgramlamaEmbedded
  3. Stack ile heap arasındaki fark nedir? Gömülü sistemlerde dinamik bellek kullanımından neden kaçınılır?OrtaC ProgramlamaEmbedded
  4. Endianness nedir? Little-endian ile big-endian farkı nedir?KolayC ProgramlamaEmbedded
  5. Bit field nedir? Donanım register'larına erişimde bit field mi yoksa bit maskesi mi kullanılmalı?OrtaC ProgramlamaEmbedded
  6. Fonksiyon pointer'ları ve callback tabloları gömülü sistemlerde nasıl kullanılır? Bir state machine örneği verin.OrtaC ProgramlamaEmbedded

Bu konuda başka bir soru biliyor musun?

Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.

Soru ekle