Supposons que j'ai les définitions suivantes:
#include <stdbool.h>
#include <stdint.h>
#define ASSERT(cond) _Static_assert(cond, #cond)
typedef union {
struct {
bool bit0:1;
bool bit1:1;
bool bit2:1;
bool bit3:1;
bool bit4:1;
bool bit5:1;
bool bit6:1;
bool bit7:1;
};
uint8_t bits;
} byte;
ASSERT(sizeof(byte) == sizeof(uint8_t));
Est-il possible d'écrire un code, tel que
#include <assert.h>
// ...
assert(((byte) { .bit0 = 1 }).bits == 0b00000001);
assert(((byte) { .bit1 = 1 }).bits == 0b00000010);
assert(((byte) { .bit2 = 1 }).bits == 0b00000100);
assert(((byte) { .bit3 = 1 }).bits == 0b00001000);
assert(((byte) { .bit4 = 1 }).bits == 0b00010000);
assert(((byte) { .bit5 = 1 }).bits == 0b00100000);
assert(((byte) { .bit6 = 1 }).bits == 0b01000000);
assert(((byte) { .bit7 = 1 }).bits == 0b10000000);
// ...
cela provoquerait un échec de compilation si les conditions ci-dessus n'étaient pas satisfaites?
(Lorsque j'essaye de placer les conditions dans la macro ASSERT
, le compilateur se plaint que expression in static assertion is not constant
, ce qui est bien sûr parfaitement logique)
La solution est autorisée à utiliser les extensions GNU du langage C.
Pas strictement dans les limites de la question, mais peut fournir une solution plus portable.
L'assertion statique a des limites aux expressions, et elle ne pourra PAS évaluer l'expression à partir d'une union.
Comme alternative, et en supposant que le code sera construit par un makefile (ou équivalent), envisagez d'ajouter une étape à la construction pour forcer la condition
static.verify: static_check.c
cc -o static_check static_check.c
./static_check
touch $@
# Make the static.verify dependency for building objects/executable.
a.o: static.verify
Fondamentalement, il est nécessaire d'exécuter le petit programme 'static_check.c'. Le programme peut produire n'importe quel message d'erreur requis. Doit quitter avec un statut de retour différent de zéro pour indiquer une erreur.