Ceci est une ancienne révision du document !
Langage C
La page de man de GCC est dans le paquet gcc-doc.
Obtenir le nom d'hôte de la machine
#include <unistd.h> char hostname[20]; gethostname(hostname, 20);
Générer un nombre aléatoire
Entre 0 et 1:
#include <stdlib.h> // rand() et RAND_MAX #include <time.h> srand(time(NULL)); float x = rand() / ((float) RAND_MAX);
Entre 0 et n (exclu):
#include <stdlib.h> // rand() et RAND_MAX #include <time.h> srand(time(NULL)); unsigned x = rand() % n;
Instructions au compilateur
#warning qchose // provoque un warning à la compilation #error qchose // provoque une erreur à la compilation
Capturer une chaîne de caractère jusqu'au retour à la ligne
sscanf(string, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor, remote_version);
Le sélecteur %[^\n] ne capture pas le \n.
Déclarer des variables dans des headers
Si on déclare et définit une variable dans un fichier d'en-tête, le linker peut rapidement générer des erreurs du type first defined here, alors qu'il pointe l'endroit de la définition.
Pour résoudre ce problème, on déclare la variable dans l'en-tête et on la définit dans le fichier source:
// .h extern const int N_MAX; //.c const int N_MAX = 1000;
(à voir si c'est vraiment du code propre…)
Attributs GCC
Variable inutilisée
static int trace_loop __attribute__((unused)) = 0;
Ne pas optimiser une fonction
float __attribute__((optimize("O0"))) scalar_avx_product(float* a, float* b)
Effacer une ligne affichée à l'écran
\rreplace le curseur au début de la ligne, et écrit par dessus le contenu déjà écrit.\33[2Kefface toute la ligne, mais ne repositionne pas le curseur au début. À utiliser avec\33[2K\rdonc.\e[1;1H\e[2Jefface tout l'écran
Convertir une chaîne de caractères en entier
C'est la fonction atoi !
Préprocesseur
Utiliser un paramètre dans une chaîne de caractère
#define PSQR(x) printf("The square of " #x " is %d.\n",((x)*(x))) PSQR(y); // The square of y is 25.
#define FORMAT "%04d" printf("Value: "FORMAT"\n", value);
(source)
Utiliser un paramètre comme préfixe
#define MY_VAR(var) int var##_my; MY_VAR(truc) // truc_my;
Pointeurs et constantes
int *const ptr = &var1; // l'adresse stockée dans ptr est constante ptr = &var2; // interdit const int* ptr = &var1; // la valeur à l'adresse stockée dans ptr est constante *ptr = 1; // interdit // possibilité d'utiliser les deux en même temps: const int* const ptr = &var1; *ptr = 1; // interdit ptr = &var2; // interdit
Incrémentations
int i = 2; int j = i++; // j = 2 et i = 3 // retourne la valeur initiale et incrémente ensuite i = 2; int k = ++i; // k = i = 3 // retourne la valeur incrémentée
Constantes de préprocesseur
Epsilon flottant
C'est la constante FLT_EPSILON pour les float ou DBL_EPSILON pour les double, définies dans le fichier d'en-tête float.h (source).
Pi
M_PI dans math.h
Connaître toutes les constantes définies par GCC
gcc -march=native -dM -E - </dev/null
Threads
Binder un thread sur un coeur
Sans hwloc, utiliser pthread_setaffinity_np().
En ligne de commande:
taskset -c 0 bash
Nommer un thread
#define _GNU_SOURCE // au tout début du fichier // ... pthread_setname_np(pthread_self(), "Thread foo");
Le nom du thread est limité à 15 caractères. Cette fonction n'est pas portable.
Formats de printf
Ajouter un certain nombre de zéros en préfixe (et ne pas les afficher si le nombre est suffisamment grand): %02d (pour 5 affiche 05 et pour 15 affiche 15). On peut se servir de cette technique pour forcer un espace si le nombre est positif et remplacer cet espace par le signe négatif sinon: % 2d. Dans le cas où on a toujours le même signe, le caractère espace n'est pas nécessaire.
Tester l'architecture
#if defined(__x86_64__) printf("x86_64 !\n"); #else printf("autre\n"); #endif
Voir https://sourceforge.net/p/predef/wiki/Architectures/ pour une liste de possibilités.
Il y a aussi cette page qui permet de tester plein de choses.
Ce mémo est aussi intéressant.
Désactiver les asserts
Déclarer la variable de préprocesseur NDEBUG avant l'inclusion de assert.h (source)
Tester si l'entrée standard est une redirection
#include <stdio.h> #include <io.h> if (isatty(fileno(stdin))) printf("stdin is a terminal\n"); else printf("stdin is a file or a pipe\n");
Vérifier les accès mémoires sur la pile
Compiler avec l'option –fstack-protector-all. L'option -fsanitize=address aide aussi.
Récupérer toutes les variables d'environnement
Afficher la pile d'appels
#include <execinfo.h> /* backtrace, backtrace_symbols_fd */ #include <unistd.h> /* STDOUT_FILENO */ void print_stacktrace(void) { size_t size; enum Constexpr { MAX_SIZE = 1024 }; void *array[MAX_SIZE]; size = backtrace(array, MAX_SIZE); backtrace_symbols_fd(array, size, STDOUT_FILENO); }
On peut ensuite connaître la ligne du fichier source correspondant à l'adresse donnée dans la pile d'appels avec :
addr2line -e main.out 0x4007db
#!/bin/bash readonly BACKTRACE_FILE=$1 for l in $(grep -E "^/.+\(.+\)\[.+\]" $BACKTRACE_FILE) do lib=$(echo $l | sed -E "s/(\/.+)\(.+/\1/g") addr=$(echo $l | sed -E "s/.+\((.+)\).+/\1/g") ans=$(addr2line -e $lib $addr) if [[ $ans == "??"* ]] then echo $l else echo $ans fi done
Voir le code source produit après le passage du préprocesseur
gcc -E source.c
Assembleur
Toujours colorier les messages de GCC
Ajouter l'option -fdiagnostics-color=always à la commande gcc (source).
ifunc
Mécanisme qui permet de choisir quelle fonction associer à un symbole lors de la résolution des symboles lors du lancement d'un binaire.
Gestion des caractères non-ASCII
Fichiers de suppressions pour sanitizers
Dans un fichier asan.supp :
leak:libdbus-1.so
LSAN_OPTIONS=suppressions=asan.supp,print_suppressions=0 ./programme