2016-03-06 1 views
3

J'ai regardé ce code pendant un moment. Je sais que la sortie est 50 mais je ne sais pas comment cela se produit.Vous ne savez pas comment la sortie est obtenue! Champs de bits

struct 
{ 
    unsigned m : 3; 
    unsigned n : 5; 
} b; 

int main(void) 
{ 
    b.m = 2; 
    b.n = 6; 

    printf("%d", b); 
} 

Toute aide que quelqu'un peut offrir, je l'apprécierais vraiment.

+1

Ceci appelle ** un comportement non défini ** - tout peut arriver. –

+0

C'est ce que je pensais. C'est une question de pratique pour un examen que j'ai à venir, donc apparemment, il est censé faire quelque chose. Je suis seulement censé répondre avec la sortie – guy25

+0

Ok, mais gardez à l'esprit que le papier de pratique est faux, alors (sauf si la réponse attendue est "comportement indéfini" ...) –

Répondre

1

Eh bien, il semble qu'un struct avec bitfields consécutifs se compacter et quand est passé à printf avec le spécificateur de format %d, cela se manifeste comme une sorte de « l'agrégation de bits » (voir note). Après quelques essais avec des valeurs différentes et comme, je suis venu avec le schéma suivant:

Les membres struct (bitfields) sont alignés ainsi:

 
n n n n n m m m 

dire dans « décroissant » ordre - dernière vient en premier.

Puis, en main, bm obtient la valeur 2 qui, en binaire est 10 et dans le format trois chiffres est 010, et bn obtient la valeur 6 qui, en binaire est 110 et dans le format à 5 chiffres est 00110, si vous vous retrouvez avec 00.110.010 qui a une valeur de ... décembre 50.


Pour tester cette hypothèse plus que je a élargi le struct b avec un autre membre et vérifié si elle tient toujours:

#include <stdio.h> 

struct { 
    unsigned m : 3; 
    unsigned n : 5; 
    unsigned o : 5; 
} b; 

int main(void) { 
    b.m = 1; 
    b.n = 1; 
    b.o = 1; 
    printf("%d\n",b); 
    return 0; 
} 

Selon l'hypothèse, les membres de la structure doit être aligné de cette façon:

 
o o o o o n n n n n m m m 

et les valeurs qui leur sont assignées dans main (c.-à-1, 1 et 1) ce qui devrait donner lieu au 0000100001001 binaire qui, en décembre est 265.

et les rendements en cours d'exécution Compiler:

$ gcc -Wall -o stprint stprint.c 
stprint.c: In function ‘main’: 
stprint.c:13:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct <anonymous>’ [-Wformat=] 
    printf("%d\n",b); 
    ^
$ ./stprint 
265 

-à-dire un résultat (très probablement) vérifie l'hypothèse. J'espère faire la lumière sur ce comportement.


Modifier/Remarque: Dans le cas où il ne ressort pas de ce qui précède, que d'autres commentateurs ont souligné, ce comportement dépend de la mise en œuvre, ce qui signifie qu'il appartient au compilateur de décider si ce « bit l'agrégation "a lieu ou non, et quel est l'ordre spécifique. Il faut aussi prendre en compte l'endianness de la plate-forme sous-jacente (voir here par exemple) Pour ce post gcc version 4.8.4 a été utilisé dans un système Ubuntu.

+0

Oui, plusieurs champs de bits adjacents sont généralement regroupés (bien que ce comportement soit défini par l'implémentation): Il est spécifique à l'implémentation s'ils sont et s'ils sont emballé de gauche à droite ou dans l'autre sens. Source: http://fr.cppreference.com/w/cpp/language/bit_field – eckes

+0

@eckes Oui, cela va sans dire. C'est pourquoi je me suis référé à cela comme un «schéma» et une hypothèse; rien de défini ici. L'idée de ce poste était de donner un "coup de pied" dans la pensée bitfield-sage en essayant de déchiffrer un comportement étrange. Dans ce cas, c'était un ordre "décroissant"; dans d'autres ne pourrait pas. Merci pour le lien BTW. – sokin