Article de reference

limiter

Dans le langage de programmation C , restrict est un mot-clé , introduit par la norme C99 , qui peut être utilisé dans les déclarations de pointeur . En ajoutant ce qualificateu...

Dans le langage de programmation C , restrictest un mot-clé , introduit par la norme C99 , qui peut être utilisé dans les déclarations de pointeur . En ajoutant ce qualificateur de type , un programmeur indique au compilateur que pendant la durée de vie du pointeur, aucun autre pointeur ne sera utilisé pour accéder à l'objet vers lequel il pointe. Cela permet au compilateur d'effectuer des optimisations (par exemple, la vectorisation) qui n'auraient pas été possibles autrement.

restrictlimite les effets de l'aliasing de pointeur , facilitant ainsi les optimisations . Si la déclaration d'intention n'est pas respectée et que l'objet est accédé par un pointeur indépendant, cela entraînera un comportement indéfini .

Optimisation

Si le compilateur sait qu'il n'y a qu'un seul pointeur vers un bloc de mémoire, il peut produire un code mieux optimisé. Par exemple :

void updatePtrs ( taille_t * ptrA , taille_t * ptrB , taille_t * val ) { * ptrA += * val ; * ptrB += * val ; }

Dans le code ci-dessus, les pointeurs ptrA, ptrBet val peuvent faire référence au même emplacement mémoire , de sorte que le compilateur peut générer un code moins optimal :

; Machine RISC hypothétique. 
ldr r12 , [ val ] ; Charger la mémoire à val dans r12. ldr r3 , [ ptrA ] ; Charger la mémoire à ptrA dans r3. add r3 , r3 , r12 ; Effectuer l'addition : r3 = r3 + r12. str r3 , [ ptrA ] ; Stocker r3 dans l'emplacement mémoire ptrA, en mettant à jour la valeur. ldr r3 , [ ptrB ] ; 'load' peut devoir attendre que le 'store' précédent soit terminé. ldr r12 , [ val ] ; Il faut charger une seconde fois pour assurer la cohérence. add r3 , r3 , r12 str r3 , [ ptrB ]

Cependant, si le restrictmot-clé est utilisé et que la fonction ci-dessus est déclarée comme

void updatePtrs ( taille_t * restreindre ptrA , taille_t * restreindre ptrB , taille_t * restreindre val );

alors le compilateur est autorisé à supposer que ptrA, ptrBet valpointent vers des emplacements différents et la mise à jour de l'emplacement mémoire référencé par un pointeur n'affectera pas les emplacements mémoire référencés par les autres pointeurs. Le programmeur, et non le compilateur, est responsable de s'assurer que les pointeurs ne pointent pas vers des emplacements identiques. Le compilateur peut par exemple réorganiser le code, en chargeant d'abord tous les emplacements mémoire, puis en exécutant les opérations avant de réenregistrer les résultats en mémoire.

ldr r12 , [ val ] ; Notez que val n'est désormais chargé qu'une seule fois. ldr r3 , [ ptrA ] ; De plus, tous les 'load' au début ... ldr r4 , [ ptrB ] add r3 , r3 , r12 add r4 , r4 , r12 str r3 , [ ptrA ] ; ... tous les 'store' à la fin. str r4 , [ ptrB ]

Le code assembleur ci-dessus est plus court car valil n'est chargé qu'une seule fois. De plus, comme le compilateur peut réorganiser le code plus librement, il peut générer du code qui s'exécute plus rapidement. Dans la deuxième version de l'exemple ci-dessus, les storeopérations ont toutes lieu après les loadopérations, ce qui garantit que le processeur n'aura pas à se bloquer au milieu du code pour attendre que les storeopérations soient terminées.

Notez que le code généré réel peut avoir des comportements différents. L'avantage du mini-exemple ci-dessus est généralement faible, et dans les cas réels, les grandes boucles effectuant des accès importants à la mémoire ont tendance à être ce qui est vraiment aidé par la restriction.

Comme mentionné ci-dessus, le comportement du code incorrect n'est pas défini , le compilateur garantit uniquement que le code généré fonctionne correctement si le code suit la déclaration d'intention.

Prise en charge par les compilateurs C++

C++ ne dispose pas d'un support standard pour restrict, mais de nombreux compilateurs ont des équivalents qui fonctionnent généralement à la fois en C++ et en C, tels que ' s GCC et Clang__restrict__ , et 's Visual C++__declspec(restrict) . De plus, __restrictest pris en charge par ces trois compilateurs. L'interprétation exacte de ces mots-clés alternatifs varie selon le compilateur :

  • Dans les compilateurs de style Unix tels que GCC et Clang, __restrictet __restrict__ont exactement la même signification que leur homologue C. Les extensions permettent notamment de les appliquer aux types de référence et this.
  • Dans Visual C++, plusieurs qualificateurs sans alias sont fournis :
    1. __declspec(restrict)s'applique à la déclaration de fonction et indique que le pointeur renvoyé n'est pas un alias.
    2. __restrictest utilisé au même endroit que restrict, mais l'indication no-alias ne se propage pas comme dans restrict. Il est également étendu aux types d'union .

Avertissements du compilateur

Pour éviter les codes incorrects, certains compilateurs et autres outils tentent de détecter lorsque des arguments qui se chevauchent ont été transmis à des fonctions avec des paramètres marqués restrict. La norme de codage CERT C considère l'utilisation abusive restrictdes fonctions de bibliothèque marquées avec elle (EXP43-C) comme une source probable de bogues logiciels, bien qu'en novembre 2019, aucune vulnérabilité ne soit connue pour avoir été causée par cela.

  • « Projet de comité ISO/IEC 9899:TC2 » (PDF) . ISO . 6 mai 2005. pp. 108–112 le .

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index