Masquage de bit en C

Jinku Hu 12 octobre 2023
  1. Utiliser le mot-clé struct pour définir les données du masque de bits en C
  2. Utilisez struct combiné avec union pour définir les données de masque de bits en C
Masquage de bit en C

Cet article présente plusieurs méthodes pour utiliser le masquage de bits en C.

Utiliser le mot-clé struct pour définir les données du masque de bits en C

Les masques de bits sont généralement utilisés pour des opérations bit par bit afin d’accéder ou de définir des sections individuelles des structures de données de type champ de bits. D’autre part, les champs de bits sont utilisés pour stocker des données de manière efficace et réduire l’empreinte mémoire. En outre, les opérations bit par bit sont relativement plus rapides à exécuter sur le matériel que les opérations arithmétiques courantes. Dans l’exemple suivant, nous démontrons l’implémentation du champ de bits en utilisant le mot-clé struct.

Notez qu’il s’agit d’une notation spéciale pour construire l’objet où les régions de bits données peuvent être récupérées en utilisant l’opérateur d’accès membre conventionnel. La structure Bitfield stocke un seul entier unsigned occupant 32 bits en mémoire, mais il peut également être accédé dans 3 sections différentes de taille - 23 bits, 5 bits, et 4 bits nommés respectivement year, day et month. En conséquence, le Bitfield représente l’abstraction de la date mise en œuvre efficacement dans la mémoire.

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

struct {
  uint32_t year : 23;
  uint32_t day : 5;
  uint32_t month : 4;
} typedef Bitfield;

int main() {
  Bitfield date = {2020, 13, 12};

  printf("sizeof Bitfield: %lu bytes\n", sizeof(date));
  printf("date: %d/%d/%d \n", date.day, date.month, date.year);

  return EXIT_SUCCESS;
}

Production :

sizeof Bitfield: 4 bytes
date: 13/12/2020

Utilisez struct combiné avec union pour définir les données de masque de bits en C

On peut aussi ajouter le mot-clé union à la structure précédente pour qu’il soit possible d’accéder à l’ensemble du numéro 32 bits séparément. Comme l’accès aux membres du champ de bits est plus lent que l’accès au membre de struct, nous affecterons la valeur de la date en utilisant les opérations sur les bits au membre entier séparé ydm.

Notez que les nombres décimaux représentant la date donnée sont logiquement mis en OU les uns avec les autres, mais avant cela, les valeurs year et month sont décalées de 23 et 28 places vers la gauche, respectivement. Ces derniers nombres sont pris en fonction des positions binaires correspondantes que ces membres occupent dans le champ binaire. Notez que chaque membre peut toujours être consulté séparément lorsque cela est nécessaire pour imprimer la sortie.

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

union {
  struct {
    uint32_t year : 23;
    uint32_t day : 5;
    uint32_t month : 4;
  };
  uint32_t ydm;
} typedef BitfieldFast;

int main() {
  BitfieldFast date_f;
  date_f.ydm = 2020 | (13 << 23) | (12 << 28);

  printf("sizeof BitfieldFast: %lu bytes\n", sizeof(date_f));
  printf("date_f: %d/%d/%d \n", date_f.day, date_f.month, date_f.year);

  return EXIT_SUCCESS;
}

Production :

sizeof BitfieldFast: 4 bytes
date_f: 13/12/2020

Un autre exemple typique d’utilisation de masque de bits est celui des adresses IP dans les réseaux. En d’autres termes, les adresses IP sont fournies avec le masque de réseau, qui détermine à quel réseau appartient l’adresse donnée. Le calcul de l’adresse de réseau est effectué par l’association logique ET de l’adresse IP et de son masque de réseau. Dans ce cas, nous avons défini le champ de bits struct pour stocker l’adresse IP et le masque de réseau séparément. Notez que le ET logique est effectué sur l’ensemble des valeurs 32 bits, mais lorsque nous imprimons les adresses sous forme de quatre sections 8 bits, l’opérateur d’accès membre est utilisé.

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

union {
  struct {
    uint8_t first : 8;
    uint8_t second : 8;
    uint8_t third : 8;
    uint8_t fourth : 8;
  };
  uint32_t ip;
} typedef IPAddress;

int main() {
  IPAddress ip1 = {10, 127, 5, 1};
  IPAddress mask = {255, 255, 240, 0};
  printf("ip1: %d.%d.%d.%d\n", ip1.first, ip1.second, ip1.third, ip1.fourth);
  ip1.ip = ip1.ip & mask.ip;
  printf("net: %d.%d.%d.%d\n", ip1.first, ip1.second, ip1.third, ip1.fourth);

  return EXIT_SUCCESS;
}

Production :

ip1: 10.127.5.1
net: 10.127.0.0
Auteur: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook