[C TOTW 5] bitfields !
|
22-09-2014, 12h58
Message : #1
|
|
ark
Psyckomodo! Messages : 1,033 Sujets : 48 Points: 317 Inscription : Sep 2011 |
[C TOTW 5] bitfields !
Yop all :)
Alors non il ne s'agit pas de la Nieme version d'un certain jeu vidéo (dsl, pas pu m'en empêcher) mais bien d'une fonctionnalité méconnue du langage C, les bitfields, ou champs de bits en Français. De quoi s'agit il ? Simplement, de variable qui vont avoir une taille, que l'on va pouvoir spécifier en nombre de bits. Mais il y a une petite restriction principale, c'est qu'il faut que ce soit fait dans une structure (ou dans un union, mais je détaillerais ça plus précisément dans un autre article je pense, j'ai pas encore eu le temps de faire les tests nécessaires ;)) Alors, pourquoi le faire dans une structure ? La réponse est simple, c'est que quand un programme est compile, il faut que ses instructions soient alignés sur des multiples de 2 afin que le pointeur d’exécution (contenu dans les registres eip/rip) puisse les exécuter correctement. Et pour ça, il va falloir aligner tout, les déclarations de variables, le code exécutable, les donnée, etc... Bref, si on lui file des bitfields comme ca dans la nature, le compilo va pas pouvoir s'y retrouver, il va donc vous sortir un message d'erreur. Voici donc un exemple simple de declaration d'une variable avec un taille de 2 bits: Code C :
struct bitfield { La variable i de ma structure ne pourra donc contenir qu'une valeur sur 2 bits, c'est a dire: 00, 01, 10, 11, et rien d'autre ! :) Bon, a quoi ça peut bien servir tout ça? Principalement pour réduire la tailles de grosses structures, ou encore implémenter facilement des protocoles de communication complexe, etc... C'est pas mal utilise dans le kernel linux. Voyons maintenant un peu plus en detail ce qu'on peut en faire et comment ca marche: Code C :
J'ai garde ici ma structure precedente, et je l'utilise donc pour quelques tests. Premierement, j'affiche la taille de la structure, combien ferra t'elle a votre avis ? 4 bytes ! Ben pourquoi ? On a bien dit qu'on voulait 2 bits pour la taille de la structure... Oo En fait c'est pas tres complique a comprendre, le compilo va voir que le type de la variable est unsigned int du coup il va prévoir de l'espace pour ce type. Notre i n'est qu'une portion de cet unsigned int. Ensuite, il y a un printf(), qui lui nous affiche la valeur de i. Ici, rien d'anormal, on a bien la valeur 3 a la sortie. En revanche le suivant est un peu plus étrange ! On peut voir que la valeur de i subit une pré-incrementation (pour ceux qui ne savent pas trop de quoi je parles, je vais faire un article dessus dans très peu de temps.), ce qui va donc lui donner la valeur 4 en théorie. Mais il n'en est rien, le programme nous sort la valeur 0. Comment est-ce possible ? Et bien comme pour tout autre type en programmation C, on a overflow, c'est a dire qu'on a dépasse la valeur maximale que le type pouvait supporter, cette valeur a donc subit une opération de modulo avec la valeur du nombre maximal de possibilité que peut contenir ce type. Comme cette phrase était peut être pas très claire, voici l’équivalent de ce que le compilo va faire quand vous écrivez ++s.i : i = (i + 1) % 4 Le 4 correspond aux nombres de nombres qu'on peut coder sur 2 bits. Compris ? :D C'est tout pour cette introduction, je ferais peut être un article plus détaillé a ce sujet! |
|
22-09-2014, 21h58
Message : #2
|
|
Dobry
Tueur de lamouz Messages : 206 Sujets : 25 Points: 73 Inscription : Aug 2011 |
RE: [C TOTW 5] bitfields !
Merci, mais est-il vraiment impossible de forcer l'allocation de la mémoire à seulement deux bits ?
Histoire que la structure fasse exactement la taille désirée (sans parler de l'alignement réalisé par le compilo)
Aestuārium Erudītiōnis
There are only two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors.
|
|
23-09-2014, 00h06
Message : #3
|
|
gruik
gouteur de savon Messages : 757 Sujets : 44 Points: 482 Inscription : Oct 2012 |
RE: [C TOTW 5] bitfields !
tu peux forcer l'alignement en déclarant ta structure avec un struct __attribute__((__packed__)) toto { (...)
ou plus verbeux en jouant du #pragma push() / #pragma pack(x) / déclaration / #pragma pop() (de mémoire)
Avant donc que d'écrire, apprenez à penser.
Selon que notre idée est plus ou moins obscure, l'expression la suit, ou moins nette, ou plus pure. Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément. (Nicolas Boileau, L'Art poétique) |
|
23-09-2014, 11h07
(Modification du message : 23-09-2014, 11h07 par Dobry.)
Message : #4
|
|
Dobry
Tueur de lamouz Messages : 206 Sujets : 25 Points: 73 Inscription : Aug 2011 |
RE: [C TOTW 5] bitfields !
Ok je ne pensais pas que le __packed__ fonctionnait dans ce genre de cas, par contre la taille minimale est bien d'un byte:
Code C :
Le code affiche 1 Autre petit trucs interessant: on ne peut pas récupérer l'adresse d'un bit-field J'ai une autre question, qu'on s'est posé avec Octarin hier soir, pourquoi la taille de Code C :
struct { char a: 4; short b: 14; } Code C :
struct { short b: 14; char a: 4; } Code C :
nous retourne une taille de 2, à savoir celle du short (12 + 4 = 16bits = 2 octets) donc le char n'a même pas été alloué !
Aestuārium Erudītiōnis
There are only two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors.
|
|
23-09-2014, 11h17
(Modification du message : 23-09-2014, 11h26 par Aniem.)
Message : #5
|
|
Aniem
Newbie Messages : 22 Sujets : 1 Points: 9 Inscription : Jun 2013 |
RE: [C TOTW 5] bitfields !
Le compilo aligne, sauf option contraire, ses structures sur un multiple de 4 octets.
Pour ton deuxième exemple, je dirais qu'il s'est rendu compte que ta struct n'était qu'un short et du coup le considère comme un short. une preuve : Code C :
struct foo{ renverra : Code : foo : 8 |
|
« Sujet précédent | Sujet suivant »
|
Sujets apparemment similaires… | |||||
Sujet | Auteur | Réponses | Affichages | Dernier message | |
[C TOTW 6] Xor tricks | ark | 7 | 2,372 |
06-03-2016, 23h36 Dernier message: Commodor |
|
[C TOTW 2] Parcours de tableau | ark | 5 | 1,523 |
29-09-2014, 17h44 Dernier message: crown |
|
[C TOTW 4] Equivalent de try / catch / throw en C | ark | 0 | 751 |
15-09-2014, 10h00 Dernier message: ark |
|
[C TOTW 3] #warning, #error | ark | 1 | 898 |
10-09-2014, 11h49 Dernier message: ark |
|
[C TOTW 1] Trick avec #include | ark | 10 | 2,616 |
01-09-2014, 18h23 Dernier message: Commodor |
Utilisateur(s) parcourant ce sujet : 4 visiteur(s)