web-dev-qa-db-fra.com

Pourquoi le mot-clé de registre a-t-il été créé?

En lisant Mots-clés qui ne le sont pas (ou commentaires d'un autre nom) par Herb Sutter Je suis tombé sur ces lignes:

C'est vrai, certains mots clés sont sémantiquement équivalents aux espaces blancs, un commentaire glorifié.

Et

Nous avons vu pourquoi le langage C++ traite les mots clés comme des mots réservés, et nous avons vu deux mots clés - auto et register - qui ne font aucune différence sémantique pour un programme C++. Ne les utilisez pas; ils ne sont tout simplement que des espaces, et il existe des moyens plus rapides de taper des espaces.

Si les mots clés comme auto (peut-être pas en C++ 11) et register sont sans valeur, alors pourquoi ont-ils été créés et utilisés?

Si cela ne fait aucune différence d'inclure le register avant une variable

#include<stdio.h>
int main(){
    register int a = 15;
    printf("%d\n%d\n",&a,a);
    return 0;
}

Pourquoi le programme ci-dessus donne-t-il une erreur?

test_register.c: Dans la fonction ‘main’:

test_register.c: 4: 2: erreur: adresse de la variable de registre "a" demandée

printf ("% d\n% d\n", & a, a);

Le programme suivant fonctionne en C++.

#include<iostream>
int main(){
    register int a = 15;
    std::cout<<&a<<'\n'<<a;
    return 0;
}
44
ayushgp

s'inscrire

En C, la classe de stockage register a été utilisée comme indice pour le compilateur, pour exprimer cela ne variable doit être préférentiellement stockée dans un registre . Notez que le conseil pour stocker une variable register dans un registre réel peut ou non être respecté, mais dans les deux cas, les restrictions pertinentes s'appliquent toujours. Voir C11, 6.7.1p6 (c'est moi qui souligne):

Une déclaration d'un identifiant pour un objet avec le spécificateur de classe de stockage register suggère que l'accès à l'objet soit aussi rapide que possible. La mesure dans laquelle ces suggestions sont efficaces est définie par la mise en œuvre. [note de bas de page 121]

[note de bas de page 121] L'implémentation peut traiter n'importe quelle déclaration register simplement comme une déclaration auto. Cependant, que le stockage adressable soit réellement utilisé ou non, l'adresse de toute partie d'un objet déclarée avec le spécificateur de classe de stockage register ne peut pas être calculée , soit explicitement (en utilisant l'opérateur unaire & comme indiqué au 6.5.3.2) soit implicitement (en convertissant un nom de tableau en un pointeur comme indiqué au 6.3.2.1). Ainsi, les seuls opérateurs pouvant être appliqués à un tableau déclaré avec le spécificateur de classe de stockage register sont sizeof et _Alignof.

En C++, il s'agit simplement d'un mot clé réservé inutilisé, mais il est raisonnable de supposer qu'il a été conservé pour une compatibilité syntaxique avec le code C.

auto

En C, la classe de stockage auto définit une variable de stockage automatique, mais elle n'est généralement pas utilisée car les variables fonction-locales sont auto par défaut .

De même, il est raisonnable de supposer qu'il a été initialement transféré en C++ pour la compatibilité syntaxique uniquement, bien que plus tard, il ait eu sa propre signification ( inférence de type ).

register en C avait deux objectifs:

  • Indiquez au compilateur que la variable doit être stockée dans un registre pour les performances. Cette utilisation est aujourd'hui largement obsolète.
  • Empêchez le programmeur d'utiliser la variable d'une manière qui l'empêcherait d'être stockée dans un registre. Cette utilisation n'est que quelque peu obsolète à l'OMI.

Ceci est similaire à const, qui

  • Indique au compilateur qu'une variable peut être stockée en mémoire morte.
  • Empêche le programmeur d'écrire dans la variable

À titre d'exemple, considérons cette fonction simpliste:

int sum(const int *values, size_t length) {
    register int acc = 0;
    for (size_t i = 0; i < length; ++i) {
        acc += values[i];
    }
    return acc;
}

Le programmeur a écrit register pour garder l'accumulateur hors de la pile, évitant une écriture mémoire à chaque mise à jour. Si l'implémentation devient quelque chose comme ceci:

// Defined in some other translation unit
void add(int *dest, int src);

int sum(const int *values, size_t length) {
    register int acc = 0;
    for (size_t i = 0; i < length; ++i) {
        add(&acc, values[i]);
    }
    return acc;
}

La variable acc ne peut plus être stockée dans un registre lorsque son adresse est prise pour l'appel add(), car les registres n'ont pas d'adresse. Le compilateur signalera donc &acc Comme une erreur, vous indiquant que vous avez probablement détruit les performances de votre code en empêchant acc de vivre dans un registre.

Cela était beaucoup plus important au début lorsque les compilateurs étaient plus stupides et que les variables vivaient en un seul endroit pour une fonction entière. De nos jours, une variable peut passer la majeure partie de sa vie dans un registre, étant déplacée sur la pile seulement temporairement lorsque son adresse est prise. Autrement dit, ce code:

/* Passed by reference for some reason. */
void debug(const int *value);

int sum(const int *values, size_t length) {
    int acc = 0;
    for (size_t i = 0; i < length; ++i) {
        acc += values[i];
    }
    debug(&acc);
    return acc;
}

aurait causé acc à vivre sur la pile pour la fonction entière dans les anciens compilateurs. Les compilateurs modernes conserveront acc dans un registre juste avant l'appel de debug().

Le code C moderne n'utilise généralement pas le mot clé register.

25
Tavian Barnes

La justification C99 fournit un peu plus de contexte pour le mot clé register:

Justification de la Norme internationale - Langages de programmation - C

§6.7.1 Spécificateurs de classe de stockage

Étant donné que l'adresse d'une variable register ne peut pas être prise, les objets de la classe de stockage register existent effectivement dans un espace distinct des autres objets. (Les fonctions occupent encore un troisième espace d'adressage.) Cela en fait des candidats pour un placement optimal, raison habituelle pour déclarer des registres; mais cela en fait également des candidats à une optimisation plus agressive.

10
Yu Hao