• STATISTIQUES
  • Il y a eu un total de 0 membres et 27882 visiteurs sur le site dans les dernières 24h pour un total de 27 882 personnes!
    Membres: 2 605
    Discussions: 3 579
    Messages: 32 816
    Tutoriels: 78
    Téléchargements: 38
    Sites dans l'annuaire: 58


  • ANNUAIRE
  • [FR] WeChall
    Audio: 3, Coding: 11, Cracking: 9, Crypto: 18, Encoding: 11, Exploit: 44, Forensics: 1, Fun: 6, HTTP: 6, Image: 8, Java:...
    Challenges
    [EN] Astalavista
    Un site aux ressources incontournable depuis plusieurs années, Astalavista est réellement devenue un cl...
    Hacking
    [EN] Sabre Films
    Site de challenge présenté sous la forme d'une quête. Vous êtes un détective et devrez résoudre d...
    Challenges
    [EN] Rosecode
    Programming: 36, Math: 29, Probability: 5, Sequence: 7, Crypto: 4, Brainf**k: 13, TimeRace: 4, Hack: 9
    Challenges
    [FR] dcode
    dcode.fr est le site indispensable pour décoder des messages, tricher aux jeux de lettres, résoudre des énigmes...
    Outils / Add-on
    [EN] Reddit
    Subreddit dédié à la sécurité informatique.
    Hacking
    [EN] This is legal
    Basic: 10, Realistic: 5, Programming: 1, Bonus: 11, SQL: 2, Encryption: 6, Application: 4, User Contributed: 3
    Challenges

  • DONATION
  • Si vous avez trouvé ce site internet utile, nous vous invitons à nous faire un don du montant de votre choix via Paypal. Ce don servira à financer notre hébergement.

    MERCI!




Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
[C TOTW 5] bitfields !
22-09-2014, 12h58
Message : #1
ark Hors ligne
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 {
  unsigned int i : 2;
};


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 :
#include <stdio.h>

struct {
  unsigned int i : 2;
} s;

int main(void) {

  s.i = 3;
  printf("sizeof(s) == %d\n", sizeof(s));
  printf("i = %d\n", s.i);
  printf("i = %d\n", ++s.i);
  return 0;
}


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!
+1 (3) -1 (0) Répondre
22-09-2014, 21h58
Message : #2
Dobry Hors ligne
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.
+1 (0) -1 (0) Répondre
23-09-2014, 00h06
Message : #3
gruik Hors ligne
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)
+1 (0) -1 (0) Répondre
23-09-2014, 11h07 (Modification du message : 23-09-2014, 11h07 par Dobry.)
Message : #4
Dobry Hors ligne
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 :

#include <stdio.h>
struct __attribute__((__packed__)){
    unsigned int i : 2;
} s;
int main(){
    s.i = 3;
    printf("sizeof == %d\n", sizeof(s));
    return 0;
}
 


Le code affiche 1 Smile

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; }
et
Code C :
struct { short b: 14; char a: 4; }
est la même, et vaut 4, pourtant short + char = 3, est-ce que cela est lié au padding et à l'alignement sur des multiples de 2 ? C'est d'autant plus étonnant que le compilo faire des optimisations assez interessante, par exemple
Code C :

struct {
          short c : 12;
          char d : 4;
}
 

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.
+1 (1) -1 (0) Répondre
23-09-2014, 11h17 (Modification du message : 23-09-2014, 11h26 par Aniem.)
Message : #5
Aniem Hors ligne
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{
  char a;
  char b;
  int c;
}

struct bar{
  char a;
  int c;
  char b;
}

printf("foo : %i\nbar : %i",sizeof(foo), sizeof(bar));
 


renverra :
Code :
foo : 8
bar : 12
+1 (0) -1 (1) Répondre


Sujets apparemment similaires…
Sujet Auteur Réponses Affichages Dernier message
  [C TOTW 6] Xor tricks ark 7 479 06-03-2016, 23h36
Dernier message: Commodor
  [C TOTW 2] Parcours de tableau ark 5 366 29-09-2014, 17h44
Dernier message: crown
  [C TOTW 4] Equivalent de try / catch / throw en C ark 0 132 15-09-2014, 10h00
Dernier message: ark
  [C TOTW 3] #warning, #error ark 1 182 10-09-2014, 11h49
Dernier message: ark
  [C TOTW 1] Trick avec #include ark 10 556 01-09-2014, 18h23
Dernier message: Commodor

Atteindre :


Utilisateur(s) parcourant ce sujet : 2 visiteur(s)
N-PN
Accueil | Challenges | Tutoriels | Téléchargements | Forum | Retourner en haut