====== Langage C ====== * [[:gdb|GDB]] * [[:makefile|Makefile]] * [[:valgrind|Valgrind]] * [[:pkgconfig|pkg-config]] * [[c:windows|Compiler sous Windows]] La page de man de GCC est dans le paquet ''gcc-doc''. * [[http://gauss.ececs.uc.edu/Courses/c4029/code/C-primer/c-primer.pdf]] * [[https://axcheron.github.io/playing-with-ld_preload/|Playing with LD_PRELOAD]] * [[https://jorengarenar.github.io/blog/less-known-c|Few lesser known tricks, quirks and features of C]] ou [[https://jorenar.com/blog/less-known-c|Few lesser known tricks, quirks and features of C]] * [[https://lemire.me/blog/2024/01/21/c23-a-slightly-better-c/|C23: a slightly better C]] * [[https://wordsandbuttons.online/so_you_think_you_know_c.html|So you think you know C?]] * [[https://zestedesavoir.com/articles/4559/la-norme-c23-est-dans-les-cartons-1/|La norme C23 est dans les cartons]] * [[https://github.com/theokwebb/C-from-Scratch|C from Scratch]] * [[https://bible.malcore.io/readme/the-beginning/introduction-to-c|Introduction to C]] * [[https://lemon.rip/w/c99-vla-tricks/|C99 doesn't need function bodies, or 'VLAs are Turing complete']] * [[https://developers.redhat.com/articles/2024/12/11/making-memcpynull-null-0-well-defined|Making memcpy(NULL, NULL, 0) well-defined]] * [[https://fuckingfunctionpointers.com/|How Do I Declare a Function Pointer in C?]] * [[https://embeddedor.com/blog/2024/06/18/how-to-use-the-new-counted_by-attribute-in-c-and-linux/|How to use the new counted_by attribute in C (and Linux)]] * [[https://github.com/CodeWithHarry/The-Ultimate-C-Programming-Course|The Ultimate C Programming Handbook]] * [[http://www.graphics.stanford.edu/~seander/bithacks.html|Bit Twiddling Hacks]] ==== Obtenir le nom d'hôte de la machine ==== #include char hostname[20]; gethostname(hostname, 20); ==== Générer un nombre aléatoire ==== Entre 0 et 1: #include // rand() et RAND_MAX #include srand(time(NULL)); float x = rand() / ((float) RAND_MAX); Entre 0 et n (exclu): #include // rand() et RAND_MAX #include 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 ==== [[https://www.developpez.net/forums/d513845/c-cpp/c/debuter/compilation-multiple-definition-first-defined-here/#post3078001|Source]] 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 === [[https://stackoverflow.com/questions/15053776/how-do-you-disable-the-unused-variable-warnings-coming-out-of-gcc-in-3rd-party-c|Source]] 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 ==== [[https://stackoverflow.com/questions/1508490/erase-the-current-printed-console-line|Source]] * ''\r'' replace le curseur au début de la ligne, et écrit par dessus le contenu déjà écrit. * ''\33[2K'' efface toute la ligne, mais ne repositionne pas le curseur au début. À utiliser avec ''\33[2K\r'' donc. * ''\e[1;1H\e[2J'' efface 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); ([[https://stackoverflow.com/questions/12958925/expand-macros-inside-quoted-string|source]]) === Utiliser un paramètre comme préfixe === #define MY_VAR(var) int var##_my; MY_VAR(truc) // truc_my; ==== Pointeurs et constantes ==== * [[https://www.thegeekstuff.com/2012/06/c-constant-pointers/]] 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'' ([[https://www.thebookofc.com/floating-point/comparing-floats-using-epsilon/|source]]). === Pi === ''M_PI'' dans ''math.h'' === Connaître toutes les constantes définies par GCC === gcc -march=native -dM -E - ==== 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 [[https://sourceforge.net/p/predef/wiki/Home/|cette page]] qui permet de tester plein de choses. [[https://wiki.debian.org/ArchitectureSpecificsMemo#Summary|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''** ([[https://stackoverflow.com/questions/5354314/how-can-i-completely-disable-calls-to-assert|source]]) ==== Tester si l'entrée standard est une redirection ==== [[https://stackoverflow.com/a/1312957|Source]] #include #include if (isatty(fileno(stdin))) printf("stdin is a terminal\n"); else printf("stdin is a file or a pipe\n"); ==== _Generic ==== * [[https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/c11-generic/|Workarounds for C11 _Generic]] * [[https://medium.com/@pauljlucas/generic-in-c-d7ab47e3b5ab|_Generic in C]] * [[https://en.cppreference.com/w/c/language/generic.html|Generic selection (since C11)]] * [[http://www.robertgamble.net/2012/01/c11-generic-selections.html|C11 - Generic Selections]] ==== 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 ==== * [[https://stackoverflow.com/questions/2085302/printing-all-environment-variables-in-c-c]] ==== Afficher la pile d'appels ==== [[https://stackoverflow.com/questions/3899870/print-call-stack-in-c-or-c|Source]] #include /* backtrace, backtrace_symbols_fd */ #include /* 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 ==== * [[https://blog.malicious.group/inline-assembly/|Inline Assembly]] * [[https://s-mazigh.github.io/ASMx86_64/index.html|ASM x86_64]] * https://diveintosystems.org/book/C7-x86_64/index.html * [[https://yuriygeorgiev.com/2024/02/19/x86-64-cpu-architecture-the-stack/|x86/x64 CPU architecture: the stack & stack frames]] * [[https://cs.brown.edu/courses/cs033/docs/guides/x64_cheatsheet.pdf|x64 Cheat Sheet]] ==== Toujours colorier les messages de GCC ==== Ajouter l'option ''-fdiagnostics-color=always'' à la commande ''gcc'' ([[https://stackoverflow.com/questions/26070873/how-to-set-gcc-colors-in-gcc4-9-to-emit-colorizing-diagnostics-messages|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. * [[https://jasoncc.github.io/gnu_gcc_glibc/gnu-ifunc.html|GNU Indirect Function and x86 ELF ABIs]] * [[https://willnewton.name/2013/07/02/using-gnu-indirect-functions/|Using GNU indirect functions]] * [[https://maskray.me/blog/2021-01-18-gnu-indirect-function|GNU indirect function]] ==== Gestion des caractères non-ASCII ==== * [[https://stackoverflow.com/questions/32523898/c-reading-non-ascii-characters|c reading non ASCII characters]] ==== Fichiers de suppressions pour sanitizers ==== * [[https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer#suppressions]] Dans un fichier ''asan.supp'' : leak:libdbus-1.so LSAN_OPTIONS=suppressions=asan.supp,print_suppressions=0 ./programme