Question

Si je suis le droit de mot-clé restrict C99, qualifier un pointeur avec elle est une promesse faite que les références données qu'il ne seront pas modifiés dans le dos du compilateur par aliasing.

En revanche, la façon dont je comprends le qualificatif de const est que la documentation appliquée compilateur qu'un objet donné ne sera pas modifié le dos d'un code d'écriture de l'être humain. Le compilateur peut obtenir un indice comme un effet secondaire, mais en tant que programmeur, je ne vraiment se soucient pas.

De même, serait-il opportun d'envisager une qualification de restrict dans un prototype de fonction comme condition que l'utilisateur garantit un accès exclusif ( « éviter aliasing », ou peut-être quelque chose de plus fort) pendant toute la durée de l'appel? Faut-il être utilisé comme "documentation"?

Aussi, est-il quelque chose à comprendre dans le fait que restrict qualifie un pointeur plutôt que les données qu'il pointe vers (comme const fait)?

EDIT:. Je croyais que l'origine restrict pourrait avoir des implications avec le code threadé, mais cela semble mal donc je supprimer les références aux fils de la question afin d'éviter la confusion des lecteurs

Était-ce utile?

La solution

La meilleure « intuition » d'avoir sur le restreindre mot-clé est que sa garantie (par le programmeur au compilateur) que, pour la durée de vie du pointeur, la mémoire accessible via ce pointeur uniquement accessible via ce pointeur et non par un autre pointeur ou une référence ou une adresse globale. Il est donc important que son sur un pointeur comme une propriété à la fois le pointeur et la mémoire, attacher les deux ensemble jusqu'à ce que le pointeur est hors de portée.

Autres conseils

Chris Dodd a la description correcte du mot-clé. Dans certaines plates-formes, il peut être très important pour des raisons de performance, car il permet au compilateur qu'une fois qu'il a données chargé par ce pointeur sur un registre, il n'a pas besoin de le faire à nouveau. Sans cette garantie, le compilateur doit recharger les données via un pointeur à chaque fois que tout autre pointeur peut-aliasing est écrit à travers, ce qui peut provoquer un décrochage sérieux pipeline appelé load-hit magasin .

const et restrict sont des concepts différents, et il est pas le cas que const implique restrict. Tout const dit est que vous ne serez pas écrire par ce pointeur dans le cadre de cette fonction . Un pointeur const peut encore être aliasé. Par exemple, considérons:

int foo( const int *a, int * b )
{
   *b *= 2;
   return *a + *b; // induces LHS: *a must be read back immediately
                   // after write has cleared the store queue
}

Alors que vous ne pouvez pas écrire directement à a dans cette fonction, il serait parfaitement légal pour vous d'appeler foo comme:

int x = 3;
foo( &x, &x );  // returns 12

restrict est une autre garantie. Promesse que a != b dans tous les appels à foo()

J'ai écrit sur le mot-clé restrict et ses implications sur les performances à longueur et

La plupart de ce que vous savez est faux!

const ne pas garantie que quelque chose ne changera pas dans le dos du compilateur. Tout ce qu'il fait est d'arrêter d'écrire à cet endroit. Quelque chose d'autre pourrait encore être en mesure d'écrire à cet endroit, donc le compilateur ne peut pas supposer qu'il est constant.

Comme d'autres l'ont dit, le qualificatif est de restreindre aliasing. En fait, au cours du premier cycle de normalisation C, il y avait une proposition de mot-clé « de noalias ». Malheureusement, la proposition a été assez mal écrit - il a poussé la seule et unique fois que le Dennis Ritchie a été impliqué au cours de ce processus, quand il a écrit une lettre qui a dit quelque chose à l'effet que « noalias doit aller Ce n'est pas ouvert à la négociation.. «

Inutile de dire que, « noalias » ne sont pas devenus partie de C. Quand il est venu le temps d'essayer à nouveau, la proposition a été assez écrit mieux que limiter a été inclus dans la norme - et même si noalias aurait probablement été nom plus significatif pour elle, ce nom était tellement viciée que je doute tout le monde a même envisagé d'essayer de l'utiliser.

Dans tous les cas, l'intention première de limiter est de dire au compilateur qu'il n'y aura pas un alias de cet article. L'une des raisons pour cela est de laisser les choses être stockées dans des registres temporairement. Par exemple, pensez à quelque chose comme:

void f(int *a, int *b, int *c) { 
    for (int i=0; i<*a; i++)
        *b += c[i];
}

Le compilateur veut vraiment je mettre dans un registre, et charger * un dans un registre, alors quand vient le temps de décider d'exécuter une autre itération de la boucle, il compare simplement les valeurs dans celles des registres à l'autre . Malheureusement, il ne peut pas le faire - si quelqu'un qui a utilisé cette fonction était complètement fou, et a appelé avec un b ==, chaque fois qu'il écrit à * b dans la boucle, cette nouvelle valeur est la valeur de * a - il doit lire * une de la mémoire à chaque itération de la boucle, juste au cas où celui qui a appelé était complètement fou. L'utilisation de restreindre Informe le compilateur peut générer du code en supposant que a et b seront toujours distinctes, l'écriture ainsi * un * ne changera jamais b (ou vice versa).

Votre compréhension est en grande partie correcte. Le qualificatif restrict indique simplement que les données accédées par un pointeur si qualifié est uniquement accessible par ce pointeur exact. Elle s'applique à se lit comme puits comme l'écrit.

Le compilateur ne se soucie pas de threads simultanés, il n'a pas été va générer du code différemment, et vous pouvez écraserait vos propres données que vous le souhaitez. Mais il n'a pas besoin de savoir ce que les opérations pointeur peut changer ce que la mémoire globale.

Restrict porte également avec lui un avertissement de l'API pour l'homme qui est mis en œuvre une fonction donnée à la prise en charge des paramètres non replié.

Aucun verrouillage par l'utilisateur est nécessaire dans la mesure où le compilateur est concerné. Il veut seulement assurer qu'il lit correctement les données qui étaient supposé à clobbered, par le code le compilateur était censé générer , dans le cas où il n'y a pas de qualification restrict. Ajout restrict il libère de cette préoccupation.

Enfin, notez que le compilateur est susceptible d'être déjà l'analyse aliasing possible en fonction des types de données, aux niveaux plus élevés d'optimisation, donc restrict est important surtout pour les fonctions avec plusieurs pointeurs vers le même type de données. Vous pouvez prendre une leçon de ce sujet et assurez-vous que tout aliasing délibéré, vous ne se fait via un union.

On peut voir restrict en action:

void move(int *a, int *b) {     void move(int *__restrict a, int *__restrict b) {
    a[0] = b[0];                    a[0] = b[0];
    a[1] = b[0];                    a[1] = b[0];
}                               }
    movl    (%edx), %eax            movl    (%edx), %edx
    movl    %eax, (%ecx)            movl    %edx, (%eax)
    movl    (%edx), %eax            movl    %edx, 4(%eax)
    movl    %eax, 4(%ecx)

Dans la colonne de droite, avec restrict, le compilateur n'a pas besoin de relire b[0] de la mémoire. Il a pu lire b[0] et de le conserver dans le registre %edx, et puis juste enregistrer le registre deux fois à la mémoire. Dans la colonne de gauche, il ne savait pas si le magasin à a peut avoir changé b.

Quelqu'un plus familier avec la norme pourrait probablement donner une meilleure réponse, mais je vais lui donner un coup de feu.

« Les données ne seront pas modifiées dans le dos du compilateur » ressemble plus à l'opposé de « volatile » pour moi.

« const » signifie que les données ne seront pas modifiées en face du programmateur; qui est, elle ne peut pas modifier les données à travers le signifiant marqué comme « const » (j'écris « signifiant » parce que dans int const *pi, le nom pi ne const, mais *pi est). Les données peuvent être modifiables par l'intermédiaire d'un autre signifiant (données non const peuvent être transmis à une fonction en tant que données const, après tout).

Ce « restreindre » qualifie des pointeurs est la clé. Les pointeurs sont le seul moyen de données d'alias dans C, ils sont donc la seule façon que vous pouvez accéder à un morceau de données via deux noms différents. « Restreindre » est tout de limiter l'accès de données à une voie d'accès.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top