Programmation C — Trucs et astuces

Manipulation des char

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

char* print_val() {
    char* buf = malloc(20);
    strcpy(buf, "Test");
    printf("in-fct buf is %s\n", buf);
    return(buf);
}

int main()
{
    char *nbuf = print_val();

    printf("Main buf is %s\n", nbuf);

    return 0;
}

RĂ©-assignement d'un char array

char rtclib_buffer[] = "YYYY-MM-DD hh:mm:ss";
// Faire quelque chose avec rtclib_buffer
strcpy(rtclib_buffer, "YYYY-MM-DD hh:mm:ss"); // Et le ramener Ă  sa valeur initiale

Binary operations

Masques rapides

D’après OpenClassrooms

var = var | ( (1<<2) | (1<<4) | (1<<5) ); // Soit var | 0b0011 0100

Note: pour visualisation avec Python.

"{:08b}".format((1<<4) | (1 << 2) | (1<<5))
#'00110100'

Vérifier la valeur d’un bit

Il faut décaler la variable à tester vers la droite jusqu’à ce que le bit à tester soit devenu le bit de poids faible, puis faire un AND 1.

uint8_t value = 0b10101010;
(value >> 3) & 1; // True, le bit 4 vaut 1
(value >> 4) & 1; // False, le bit 5 vaut 0.

Note : cette astuce peut être utilisée pour vérifier si un entier est pair. Un entier pair a son bit de poids faible égal à 0, un entier impair a son bit de poids faible égal à 1.

Modification de la valeur d’un bit

Les snippets suivants permettent de modifier sélectivement un unique bit parmi de nombreux autres. Ils sont inspirés par ce post sur Stackexchange

Mettre un bit à zéro

La mise à zéro se fait en combinant l’opérateur ET (&) et l’opérateur NOT (~).

uint8_t value = 0b11111111;
value = value & ~((uint8_t)1 << 4);
printf("%b\n", value);
// Doit renvoyer « 0b1110111 »

Explications On exploite ici la table de vérité de la fonction ET.

Bit 1 Bit 2 Bit 1 & Bit 2
0 0 0
1 0 0
0 1 0
1 1 1
(uint8_t)1 // Cast 1 vers un entier Ă  8 bits
// Renvoi = 0b0000 0001
(uint8_t)1 << 4 // Ce 1 est décalé de 4 bits vers la gauche
// Renvoi = 0b0001 0000
~((uint8_t)1 << 4) // On inverse tous les bits
// Renvoi = 0b1110 1111

value = 0b01010101
value & ~((uint8_t)1 << 4) // On applique ce masque sur la valeur de base
/*
 0b01010101
&0b11101111
-----------
 0b01000101
*/

Mettre un bit Ă  1

On utilise cette fois le simple opérateur OR (|).

uint8_t value = 0b10000000;
value = value | ((uint8_t)1 <<5);
printf("%b\n", value);
// Doit renvoyer « 0b10100000 »

Explications Cette fois ci, on utilise la table de vérité de la fonction OU, qui renvoie un 1 si au moins l’une des deux valeurs est 1.

Bit 1 Bit 2 Bit 1 & Bit 2
0 0 0
1 0 1
0 1 1
1 1 1

Pour l’opération ci-dessus, on a :

   1000 0000b
OR 0010 0000b
-------------
=  1010 0000b

Inverser un bit

On utilise le XOR / Ou Exclusif (^);

uint8_t value = 0b10100000;
value = value ^ ((uint8_t)1 <<5);
printf("%b\n", value);
// Doit renvoyer « 0b10000000 »

Explications La table de vérité utilisée est celle de la fonction OU EXCLUSIF, qui renvoie un 1 si et seulement si l’une des deux valeurs est 1, et renvoie 0 lorsque les deux valeurs sont identiques.

Bit 1 Bit 2 Bit 1 & Bit 2
0 0 0
1 0 1
0 1 1
1 1 0

Pour l’opération ci-dessus, on a :

    1010 0000b
XOR 0010 0000b
--------------
=   1000 0000b

Le 7ème bit de chaque nombre étant à 1, leurs valeurs « s’annulent » selon la table de vérité de la fonction XOR, et le bit est passé à zéro. On remarque que le 8ème bit du premier nombre est à 1, et celui du second est à 0. Le résultat est inchangé, on garde bien un 1.