Question

En C, nous ne pouvons pas utiliser et pour trouver l'adresse d'une variable de registre, mais en C ++, nous pouvons faire la même chose. Pourquoi est-il légal en C ++, mais pas en C? Quelqu'un peut-il s'il vous plaît expliquer ce concept en profondeur.

Était-ce utile?

La solution

Voici un extrait de la section 6.7.1 (note 101) du norme C99 (pdf) :

  

La mise en œuvre peut traiter toute déclaration de register simplement comme une déclaration de auto. Cependant, si le stockage adressable est effectivement utilisé, l'adresse d'une partie d'un objet déclaré avec registre spécificateur de classe de stockage ne peut pas être calculé , soit explicitement (par l'utilisation de l'opérateur unaire & comme indiqué dans 6.5.3.2) ou implicitement (par la conversion d'un nom de tableau à un pointeur tel que discuté dans 6.3.2.1). Ainsi, le seul opérateur qui peut être appliqué à un tableau déclaré avec spécificateur de classe de stockage register est sizeof.

Et de la section 7.1.1, paragraphe 3 de la C ++ standard (pdf) :

  

Un spécificateur de register a la même sémantique en tant que prescripteur de auto avec une allusion à la mise en œuvre que l'objet ainsi déclarée sera fortement utilisé. [Note: l'indice peut être ignoré et dans la plupart des implémentations, il sera ignoré si l'adresse de l'objet est prise. Note -end]

petits morceaux amusants sur register

Le groupe C ++ (WG21) veut conjurer register :

  

Le mot-clé register sert très peu de fonction, offrant plus d'un soupçon qu'une note dit est généralement ignorée. Il devrait être dépréciée dans cette version de la norme, libérant ainsi le nom réservé pour une utilisation dans une future norme, un peu comme auto a été réutilisé cette fois pour être de la même inutile.

     

Notes du Mars, réunion 2009:

     

Le consensus du CWG était en faveur de la dévalorisation register.

Regardez ce que le groupe C99 (GT14) dit a propos de register (pdf) lors d'une réunion:

  

Accord général à désapprouver le mot-clé « auto ». Faut-il demander WG21 de revenir à   l'utilisation antérieure de « register » (pas d'adresse)? Non, ce ne sera pas voler avec WG21.

Autres conseils

Le mot-clé de registre est un seul indice et peut être ignoré. La plupart des compilateurs C ++ ignorent tout le temps, mais tout compilateur C ++ ignoreront si vous prenez l'adresse de la variable, ou créer une référence.

D'autre part, un compilateur C ++ ne pas Vous pour ignorer « register » juste parce que vous prenez l'adresse de la variable. En théorie, le compilateur peut stocker dans un registre et vous donner une valeur de pointeur magique qui est en quelque sorte mis en correspondance avec le registre dans les coulisses, mais ce serait beaucoup de travail pour un gain très peu, donc pas de compilateur (que je connais) fait quelque chose comme ça.

Depuis registre est ignorable en C et, je soupçonne que la proscription explicite contre la prise d'adresses des variables de registre était simplement pour alléger les compilateurs C de la charge de vérifier cela.

La partie pertinente de la norme C ++ est 7.1.1.3:

  

Un spécificateur de registre a la même sémantique que spécificateur auto avec une indication pour la mise en œuvre que l'objet ainsi déclarée sera fortement utilisé. [Note: l'indice peut être ignoré et dans la plupart des implémentations, il sera ignoré si l'adresse de l'objet est prise. Note -end]

Désolé pour la réponse super fin.

Le problème est que, en C, register signifiait à l'origine à stocker des valeurs dans un registre qui est pourquoi seulement int et char peuvent être utilisés pour cela. Mais avec le temps et surtout la norme C ++, il a élargi à « l'accès rapide » plutôt que « dans le registre de la CPU ». Donc, en C ++, un tableau peut-être un type de register mais nous savons qu'il est impossible de stocker des tableaux dans un registre CPU. Par conséquent, il est logiquement correct de traiter un registre C ++ (dans le sens ci-dessus), mais toujours pas de sens si les valeurs sont en fait dans un registre CPU.

Je suppose que le mot-clé n'aurait même pas fait dans la langue s'il n'y avait pas de compatibilité C. Bien que je ne peux pas parler avec une autorité, si tel est le cas, il me semble qu'il ya une raison pratique pour qu'il soit légal au-delà de simple standard appliqué « le compilateur est plus intelligent que vous » clause: C ++ prend adresses des choses sans autorisation plus facilement que C ne. Plus précisément: les fonctions membres et références.

Parce que les fonctions membres ont besoin d'un paramètre this implicite, il serait impossible de les appeler à partir d'un objet déclaré register. En C, il n'y a rien que vous interdit de dire register struct X x;, de sorte que cette langue devrait être autorisée en C ++ [puisque C-compatibilité est toute raison, le mot-clé existe même]. Mais si vous interdisez d'appeler des fonctions membres ainsi que la prise d'adresses, qui couvre également l'appel du constructeur initial. Essentiellement, cela ne fonctionnerait pas sur les types non-POD. Donc, vous vous retrouvez avec un spécificateur de classe de stockage qui est valable uniquement pour un sous-ensemble des types juridiques, quand tout le reste peut être utilisé pour quoi que ce soit.

Vous ne pouvez pas créer aussi des références à ces objets, même si, sur le plan technique, le compilateur ne doit pas traiter les références comme pointeurs. register int i; int& x; n'est pas nécessaire d'avoir un espace pour deux variables, mais si vous le faites plus tard, vous &x retrouvez avec un pointeur vers i. Ainsi, la construction initiale doit être rendue illégale. Bien que cela semble un non-problème, étant donné que les références n'existent pas dans C de toute façon, revenir à notre point précédent, les types POD déclarés avec le spécificateur register ne peuvent plus être copiés. Le compilateur fourni constructeur de copie est de la forme X::X(const X&) ou X::X(X&) selon le cas.

Ainsi, afin de maintenir la compatibilité C, ils doivent faire register unique en tant que prescripteur de classe de stockage en ce qu'elle ne concerne pas tous les types et modifier au moins deux parties différentes de la norme ailleurs [à préciser que vous pouvez créer pas une référence à une variable déclarée avec le register de, et de travailler en quelque sorte autour des références pour la copie POD]. Ou alors, ils pourraient simplement dire « son accord pour prendre l'adresse » et laisser les compilateurs décider si oui ou non d'honorer les demandes. Quelque chose qu'ils avaient l'intention de faire de toute façon.

Une variable de registre ne possède pas d'adresse, il est tenu (au moins il est censé avoir lieu) dans un registre cpu. Étant donné que le modificateur de registre est rien, mais un indice, si vous forcez le compilateur pour générer le code pour extraire son adresse, le modificateur sera ignoré et vous vous retrouverez avec une variable ordinaire tenue en mémoire.

Pour répondre directement à votre question, quel que soit celui que vous permet de prendre une adresse de variable registre (votre message original se contredit ..) vous permet d'ignorer votre propre indice et devrait au moins émettre un avertissement. OMI, la mise en œuvre correcte serait de ne pas accorder de prendre l'adresse d'une variable de registre.

La chose importante à retenir est que « registre » est juste une indication pour le compilateur (un moment inutile à cela, je ne l'ai jamais vu aucune amélioration de la vitesse, et la plupart des compilateurs probablement simplement l'ignorer). C et C ++ sont tous deux autorisés à ignorer votre « conseils » et garder la variable en mémoire. Bien sûr, si vous prenez l'adresse de la variable, il forcera à assigner une place dans la mémoire.

C et C ++ ont juste des règles différentes sur ce que vous pouvez le faire parce qu'ils sont des langues différentes. Les concepteurs du C ont décidé de vous permettre d'obtenir l'adresse d'une variable de registre, car il ne fait pas mal quoi que ce soit; C ne vous permet pas de le faire parce qu'elle serait-elle la force dans la mémoire.

En y repensant plus, la restriction de C est probablement pour la même raison que les variables devaient être déclarées au début du bloc le compilateur peut mise en page de la mémoire pour les variables comme les rencontres, sans tenir compte de la façon dont il est utilisé plus tard dans la fonction.

Ceci est une supposition que, mais je doute que vous pouvez prendre l'adresse d'un registre en C ++ parce qu'une telle réflexion n'existe pas. C ++ ne probablement pas utiliser un registre dans votre cas particulier. Notez que la qualification de classe de stockage register est seulement une indication pour le compilateur (et la plupart, sinon tous les compilateurs modernes ignorent heureusement complètement).

C et C ++ sont deux langues différentes, avec un grand sous-ensemble commun. Voilà pourquoi certaines choses sont différentes entre eux.

Bien que je ne comprends pas votre question, register est (au moins en C ++) une indication qu'une variable peut être consulté plus souvent, et rien de plus. En C, cela signifie que vous ne pouvez pas prendre l'adresse avec l'& opérateur unaire, ce qui a une certaine quantité de sens à l'époque. Dans les premiers jours de C, il était prévu que le compilateur peut-être pas pris la peine allouer de la mémoire pour la variable, et donc il ne serait pas nécessairement une adresse à prendre.

(Les ordinateurs ont normalement des registres, qui sont des parties d'accès rapide de la CPU, et donc le plus rapide de stockage d'accès. Une variable peut vivre dans un registre, plutôt que dans la mémoire, si cela a causé une meilleure performance.)

De nos jours, presque tous les compilateurs sont assez sophistiqués pour faire leur propre allocation mieux que le programmeur peut, donc utiliser register est presque toujours inutile.

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