2016-08-26 2 views
1

Dans l'exemple suivant, la taille de complex_t est la même que uint16_t: 2 octets, mais 3 octets.Pourquoi l'empaquetage ne fonctionne-t-il pas dans les unions ou structures

Retrait de la seconde union (« proximity_unsafe ») réduit la taille de 2 octets, mais je ne peux pas comprendre le modèle des règles d'emballage.

#include <stdint.h> 
#include <stdio.h> 

typedef union { 
    uint16_t unsafe; 
    struct { 
     uint16_t backwardmotion_unsafe : 1; 
     uint16_t batteryvoltage_unsafe : 1; 
     union { 
      uint16_t dropoff_unsafe  : 4; 
      struct { 
       uint16_t dropofffrontleft_unsafe : 1; 
       uint16_t dropofffrontright_unsafe : 1; 
       uint16_t dropoffsideleft_unsafe : 1; 
       uint16_t dropoffsideright_unsafe : 1; 
      }__attribute__((__packed__)); 
     }__attribute__((__packed__)); 
     union { 
      uint16_t proximity_unsafe  : 3; 
      struct { 
       uint16_t proximityfront_unsafe : 1; 
       uint16_t proximityleft_unsafe  : 1; 
       uint16_t proximityright_unsafe : 1; 
      }__attribute__((__packed__)); 
     }__attribute__((__packed__)); 
    } __attribute__((__packed__)); 
} __attribute__((__packed__)) complex_t; 

int main() 
{ 
    printf("sizeof(complex_t): %i", sizeof(complex_t)); 
    printf("sizeof(uint16_t): %i", sizeof(uint16_t)); 
} 

Répondre

3

Parce qu'il est légal de prendre l'adresse d'un membre struct nommé qui n'est pas un champ de bits, les membres non-BITFIELD sont nécessaires pour commencer à des limites d'octet. Bien qu'il ne soit pas possible de prendre l'adresse de membres anonymes, et il serait donc théoriquement possible pour un compilateur de permettre à de tels objets de commencer à des frontières de bits arbitraires, cela impliquerait que la disposition d'une structure varie selon que ses membres ont été nommés.

+0

Excellente explication! – Catskul