11
votes

Où est stocké Rvalue en C?

in c, j'ai cette pièce de code:

int a;
a = 10 + 5 - 3


5 commentaires

Est-ce mauvais que je trouve "la pièce de code" hilarant? :)


une belle référence: Stackoverflow.com/questions/79923/...


@ejames, ça peut être ou ne pas être mauvais. Je soupçonne que le Codice n'est plus en usage général et de nombreuses personnes peuvent même ne pas savoir ce que c'est (à moins d'avoir regardé «Blackadder»).


@djbender Cette référence concerne la pile et le tas, ce qui n'est pas pertinent, ici. Comme indiqué dans plusieurs réponses, la valeur R est matérialisée en tant qu'opérande dans une instruction d'assemblage (pourrait être une série d'instructions d'assie, mais jamais - moins ces valeurs R sont des instructions ou des parties de celui-ci) et sont donc stockées avec le programme lui-même.


@mjv Hey j'ai dit que c'est une bonne référence, pas la réponse ;-)


7 Réponses :


6
votes

Typiquement, la valeur R est "stockée" dans le programme lui-même.

En d'autres termes, le compilateur lui-même ( avant que le programme ne soit jamais exécuté ) calcule les 10 + 5 - 3 valeur (cela peut le faire depuis que cela est basé sur des valeurs immédiates constantes), et il émet le code de montage pour stocker le résultat de ce calcul de la valeur L de la valeur de l'affectation (dans ce cas, la variable nommée Le compilateur sait probablement comme une adresse relative à une extrémité de données de tresse).

La valeur R, qui a une valeur de 12 ne se trouve donc que dans le binaire du programme, dans une instruction d'assemblage que a l'air comme xxx

0C est la "valeur r".

si la valeur R est arrivée Le résultat d'un calcul qui ne peut être effectué qu'au moment de l'exécution, disons si le code C sous-jacent était le suivant: A = 17 * x; // x Quelques temps d'exécution var, la valeur R serait aussi "stockée" (ou plutôt matérialisée) comme une série d'instructions dans le programme binaire. La différence avec le simple "MOV DESTS, IMM" ci-dessus est qu'il faudrait plusieurs instructions pour charger la variable X dans un accumulateur, multiplier par 17 et stocker le résultat à l'adresse où la variable A est. Il est possible que le compilateur puisse "s'autoriser" ;-) Pour utiliser la pile pour un résultat intermédiaire, etc. mais tel serait de
a) complètement dépendant du compilateur de
b)
transiante c) et n'impliquerait généralement que partie de la valeur r Il est donc sûr de dire que la valeur R est un concept temporel compilé qui est encapsulé dans des parties du programme (pas les données) et n'est stocké nulle part mais dans le programme binaire.

En réponse à Paxdiablo: l'explication proposée ci-dessus est en effet restrictive des possibilités car la norme C est efficacement pas dicter quelque chose de cette nature. Jamais moins, la plupart de toute valeur R est finalement matérialisée, au moins en partie, par certaines instructions qui définit les choses de manière à ce que la valeur appropriée, qu'elle soit calculée (au moment de l'exécution) ou immédiate soit traitée correctement.


3 commentaires

Je pense qu'il demande d'où se trouvent les différentes parties du code dans la pile.


rien dans la norme C ordonne à ce comportement. Vous devriez dire: "Typiquement, la valeur R est ...".


@paxdiablo. D'accord et édité avec "typiquement", j'ai également ajouté un petit paragraphe au bas, êtes-vous d'accord avec cela?



1
votes

C'est dépendant du compilateur. Habituellement, la valeur (12) sera calculée par le compilateur. Il est ensuite stocké dans le code, généralement dans le cadre d'une instruction de montage immédiate / déplacée immédiate.


3 commentaires

Donc, vous voulez dire (10 + 5-3) est calculé pendant la compilation? Je me demande comment le compilateur calculer cela?


C'est une bonne réponse. Implicity Dans cette réponse: l'expression "10 + 5-3" est temporairement stockée dans la mémoire de travail du compilateur, probablement comme une structure de données "arborescence d'expression". Ensuite, les optimisations du compilateur (dans ce cas, la propagation constante) «résoudre» l'arborescence d'expression où il a des valeurs constantes. Le compilateur entraînera un "12" et que 12 sera l'opérande à l'une des instructions de la langue de montage du programme.


Un bon livre sur les optimiseurs de compilation est MULNIK, conception et mise en œuvre du compilateur avancé.



5
votes

Les constantes sont probablement simplifiées lors de la compilation, de sorte que votre question comme littéralement posée peut ne pas aider. Mais quelque chose comme, disons, i - j + k code> qui doit être calculé au moment de l'exécution de certaines variables, peut être "stocké" partout où le compilateur aime, en fonction de l'architecture de la CPU: le compilateur sera typiquement Essayez de faire de son mieux pour utiliser des registres, par exemple

 LOAD AX, i
 SUB AX, j
 ADD AX, k


1 commentaires

J'ai supprimé ma réponse, alors vous voudrez peut-être sortir "Gman dit". :)



1
votes
  • Le résultat du calcul dans le RHS (côté droit) est calculé par le compilateur dans une étape appelée "propagation constante". li>
  • Ensuite, il est stocké comme un opérande de l'instruction d'assemblage déplaçant la valeur dans A code> li>

    Voici un démontage de MSVC: P>

      int a;
      a = 10 + 5 - 3;
    
    0041338E  mov         dword ptr [a],0Ch 
    

0 commentaires

1
votes

où il le stocke est en fait totalement jusqu'au compilateur. La norme ne dicte pas ce comportement.

A typique place en compilant réellement le code et en regardant la sortie de l'assembleur: xxx

qui produit: xxx

Le bit correspondant est marqué ; ***** et vous pouvez voir que la valeur est créée par le compilateur et Il suffit d'inséré directement dans une instruction MOV .

Notez que ce n'est que ce simple car l'expression est une valeur constante. Dès que vous introduisez des valeurs non constantes (comme des variables), le code devient un peu plus compliqué. C'est parce que vous devez regarder ces variables en mémoire (ou ils peuvent déjà être dans un registre), puis manipuler les valeurs à l'heure d'exécution , pas compilation-heure .

sur la manière dont le compilateur calcule quelle devrait être la valeur, c'est à voir avec l'évaluation de l'expression et est une autre question: -)


1 commentaires

Bon exemple. J'allais dire "regarder l'assemblée générée" mais j'étais trop paresseux pour créer un exemple. :) Notez également, il peut devenir plus compliqué si la valeur constante est plus grande. Certains processeurs ont une limite (par exemple 8 bits ou 16 bits) sur la manière dont une valeur peut être mise directement dans une instruction.



0
votes

Votre question est basée sur une prémisse incorrecte.

La propriété de définition de lvalue in c est qu'elle a une place de stockage, c'est-à-dire stocké . C'est ce qui différencie Lvalue de Rvalue . La rvalue est pas stockée n'importe où. C'est ce qui en fait un rvalue. S'il était stocké, il serait lvalue par définition.


2 commentaires

Il doit être stocké quelque part sinon vous ne pouvez pas l'utiliser :-)


Non, ça ne le fait pas. Par exemple, lorsque vous initialisez une variable avec 0 , le code de la machine peut simplement xor un registre avec lui-même. Est 0 "stocké quelque part" dans ce cas? N ° A 1 peut être généré comme une augmentation du registre précédemment à zéro. Etc. Les r devalues ​​ne doivent pas être stockées nulle part. C'est ce qui les rend les rempartes.



0
votes

Les termes "lvalue" et "rvalue" sont utilisés pour bisecter le monde des expressions. C'est-à-dire que (10 + 5-3) est une expression qui se trouve être une rvalue (car vous ne pouvez pas appliquer l'opérateur et l'opérateur - en C ++, les règles sont plus compliquées). Au moment de l'exécution, il n'y a pas d'expressions, de lvalues ​​ou de rapaces. En particulier, ils ne sont pas stockés nulle part.

Vous vous demandiez où la valeur 12 a été stockée, mais la valeur 12 n'est ni une lvalue ni une rvalue (par opposition à l'expression 12 qui serait une rvalue, mais 12 < / code> n'apparaît pas dans votre programme).


0 commentaires