Les attributs ci-dessous sont non standards et dépendent du compilateur. ====__attribute__((const)) et __attribute__((pure))==== Il est aussi possible d'utiliser ''%%[[gnu::pure]]%%'' et ''%%[[gnu::const]]%%''. * Définition Une fonction ''const'' ne modifie aucune donnée et ne lit que ces arguments (pas de variable globale et pas de déréférencement de pointeur, y compris parmi ses arguments). Une fonction ''pure'' ne modifie aucune donnée accessible par d'autres fonctions (généralement appelées des observateurs). Elle peut accéder en lecture seule à des variables globales ou encore déréférencer des pointeurs passés en argument. * Conséquence Les fonctions ''const'' sont garanties idempotentes. Les fonctions ''pure'' peuvent ne pas renvoyer la même valeur avec les mêmes arguments. Une variable globale ou bien le contenu d'un tableau passé en pointeur peut changer. Cependant, le compilateur va optimiser en supposant l'application ''single-thread''. Donc si deux fonctions sont appelées avec les mêmes arguments et que le compilateur est sûr que les arguments ne sont pas modifiés (y compris le contenu des pointeurs), il ne va appeler la fonction qu'une seule fois et réutiliser la valeur retour.
The const attribute imposes greater restrictions on a function’s definition than the similar pure attribute. The const attribute prohibits a function from reading objects that affect its return value between successive invocations. In general, since a function cannot distinguish data that might change from data that cannot, const functions should never take pointer or, in C++, reference arguments. [[https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes|Using the GNU Compiler Collection]], {{ :lang:c:attribut:using_the_gnu_compiler_collection_gcc_common_function_attributes_2020-03-06_20_33_39_.html |Archive v9.2 le 06/03/2020}}
Rappel : l’attribut ''pure'' n'est pas ''thread-safe'' si la fonction fait appel à une variable globale ou si un de ces arguments peut être modifiée par un autre thread. [[https://stackoverflow.com/questions/45190217/gcc-optimization-of-pure-functions|GCC optimization of pure functions]] {{ :lang:c:attribut:c_-_gcc_optimization_of_pure_functions_-_stack_overflow_2020-07-15_08_31_26_.html |Archive du 19/07/2017 le 15/07/2020}} * Exemples Ici, il faut bien activer l'option ''-O2''. ^Code^Assembleur^ |Deux appels consécutifs : optimisation. \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure1.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure1.cpp.asm 2}}| |Modification entre deux appels : pas d'optimisation. \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure2.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure2.cpp.asm 2}}| |Utilisation intermédiaire par copie par une fonction : pas d'optimisation !!! \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure3.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure3.cpp.asm 2}}| |Utilisation intermédiaire par copie par une fonction inconnue pure : optimisation. \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure4.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure4.cpp.asm 2}}| |Utilisation en lecture au milieu : optimisation. \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure5.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure5.cpp.asm 2}}| |Utilisation en écriture au milieu : pas d'optimisation. \\ \\ {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/pure6.cpp}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/pure6.cpp.asm 2}}| ====__attribute__((weak)) et extern==== * Explication Cette information va être utile au lieur. Chaque symbole (variable globale ou fonction) peut être "strong" ou ''weak''. Si un symbole "strong" existe, les symboles ''weak'' seront ignorés. Si deux symboles ''weak'' existent sans symbole "strong", le lieur prendra aléatoirement l'un des deux (voir [[lang:cpp:lieur#les_methodes_definies_dans_un_entete_ont_un_attribut_weak|lieur]]). Si deux symboles "strong" existent, le lieur va générer une erreur ''duplicate symbol''. Il est aussi possible de définir un prototype ou la déclaration d'une variable globale ''extern'' en ''weak''. Dans ce cas, si le symbole n'est pas défini, le lieur ne posera pas de problème (pas de ''undefined reference to'') et considérera que le symbole est à l'adresse ''null'' (ne pas lire ces symboles). * Exemple {{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/weak1.cpp}} Symboles : {{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/weak1.cpp.nm}} Résultat dans la sortie standard: {{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/weak1.out}} ====restrict==== Mot clé pour indiquer qu'une zone mémoire n'est accédée que par un seul pointeur. Cette restriction n'est évidemment pas thread-safe. Voir l'exemple de Wikipédia sur [[https://fr.m.wikipedia.org/wiki/Restrict|restrict]] {{ :lang:c:attribut:restrict_wikipedia_04_01_2021_20_34_41_.html |Archive du 16/04/2020 le 04/01/2021}}. ^Source^Code généré^ |{{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/restrict1.c 2}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/restrict1.c.asm 3}}| |{{gh>https://github.com/bansan85/wiki_le_garrec_fr/blob/master/cpp/attribute/restrict2.c 3}}|{{gh>https://github.com/bansan85/wiki_le_garrec_fr_travis/blob/master/cpp/attribute/restrict2.c.asm 3}}| Avec ''restrict'', il n'y a pas besoin de relire le contenu de ''*val'' entre les deux instructions.