Strict aliasing fait référence au moment où un pointeur est converti en un autre type de pointeur, après quoi le contenu est accédé. L'aliasing strict signifie que les types pointés impliqués doivent être compatibles. Cela ne s'applique pas ici. Il existe cependant le terme alias de pointeur, ce qui signifie que deux pointeurs peuvent faire référence à la même mémoire. Le compilateur n'est pas autorisé à supposer que c'est le cas ici. S'il veut faire des optimisations comme celles que vous décrivez, il devra peut-être ajouter un code machine qui compare les pointeurs les uns avec les autres, afin de déterminer s'ils sont identiques ou non. Ce qui en soi rendrait la fonction légèrement plus lente.
Pour aider le compilateur à optimiser un tel code, vous pouvez déclarer les pointeurs comme restrict
, ce qui indique au compilateur que le programmeur garantit que les pointeurs ne pointent pas sur la même mémoire.
Votre fonction compilée avec gcc -O3
de ce code machine:
0x00402D09 mov $0x1,%edx
Ce qui signifie essentiellement que toute fonction a été remplacée (inline) par "set a.x 1".
Mais si je réécris votre fonction
int test_func(A* restrict a, int* restrict x)
{
a->x = 0;
*x = 1;
return a->x;
}
et compilez avec gcc -O3
, il ne retourne 0. Parce que je l'ai maintenant dit au compilateur que a->X
et x
ne pointent pas la même mémoire, il peut Supposons que *x = 1;
n'affecte pas le résultat et ignore la ligne *x = 1;
ou la séquence avant la ligne a->x = 0;
.
Le code machine optimisé de la version restrict ignore l'appel de la fonction entière, car il sait que la valeur est déjà 0 selon votre initialisation.
Ceci est bien sûr un bug, mais le programmeur est à blâmer pour cela, pour une utilisation imprudente de restrict
.
Je ne pense pas que ce soit le but du mot-clé ['restrict'] (https://en.wikipedia.org/wiki/Restrict) dans C. – Stargateur
Je pensais que * strict aliasing * fait référence à la cas de conversion entre les types de pointeurs, en supposant que les types étaient de la même taille. Par exemple, convertir 'int *' en float * ', sur une plateforme avec' sizeof int == sizeof float'. Et je pensais que cette restriction était due au fait que chaque plate-forme peut avoir des exigences d'alignement différentes, ce qui dans certains scénarios peut conduire à un comportement indéfini. Je ne vois rien de tout cela dans votre code. –
En règle générale, vous pouvez dire qu'il ne peut y avoir de violation de '' strict aliasing '' que si vous lancez un pointeur vers un type différent ou si vous le convertissez en 'void *' et ensuite en un autre type. Ici, dans votre cas, toutes les informations de type sont présentes au compilateur, il ne doit donc pas créer de problèmes. –