Frage

in C habe ich dieses Codestück:

int a;
a = 10 + 5 - 3

Ich will fragen:Wo ist (10+5-3) gespeichert?(Soweit ich weiß, a liegt auf dem Stapel, wie wäre es? (10+5-3)?Wie wird dieser R-Wert berechnet?)

War es hilfreich?

Lösung

Normalerweise wird der R-Wert im Programm selbst „gespeichert“.

Mit anderen Worten, der Compiler selbst (bevor das Programm jemals ausgeführt wird) berechnet den 10 + 5 - 3-Wert (dies ist möglich, da alles auf konstanten unmittelbaren Werten basiert) und gibt den Assembler-Code aus, um das Ergebnis dieser Berechnung in einem beliebigen L-Wert für die Zuweisung zu speichern (in diesem Fall). In diesem Fall handelt es sich um die Variable mit dem Namen a, die der Compiler wahrscheinlich als eine Art relative Adresse zu einem Datensegmentursprung kennt.

Der R-Wert, der den Wert 12 hat, findet sich daher nur innerhalb der Binärdatei des Programms, also innerhalb einer Assembler-Anweisung sieht aus wie

  mov <some dest, typically DS-relative>, $0C 

$0C ist der „r-Wert“.

Wenn der R-Wert das Ergebnis einer Berechnung ist, die nur zur Laufzeit durchgeführt werden kann, sagen wir, der zugrunde liegende C-Code wäre:a = 17 * x;// x eine Laufzeitvariable, der R-Wert würde ebenfalls als eine Reihe von Anweisungen innerhalb der Programmbinärdatei „gespeichert“ (oder vielmehr materialisiert) werden.Der Unterschied zum einfachen „mov dest, imm“ oben besteht darin, dass mehrere Anweisungen erforderlich wären, um die Variable x in einen Akkumulator zu laden, mit 17 zu multiplizieren und das Ergebnis an der Adresse zu speichern, an der sich die Variable a befindet.Es ist möglich, dass sich der Compiler „autorisiert“ ;-), den Stack für ein Zwischenergebnis usw. zu verwenden.aber so wäre es
a) vollständig vom Compiler abhängig
b) vorübergehend
c) und würde typischerweise nur beinhalten Teil des r-Wertes
Man kann daher mit Sicherheit sagen, dass der R-Wert ein Konzept zur Kompilierungszeit ist, das in Teilen des Programms (nicht in den Daten) gekapselt und nirgendwo anders als in der Programmbinärdatei gespeichert ist.

Als Antwort auf paxdiablo:Die oben angebotene Erklärung schränkt die Möglichkeiten tatsächlich ein, da dies beim C-Standard tatsächlich der Fall ist nicht etwas in dieser Art diktieren.Nichtsdestotrotz werden die meisten R-Werte schließlich, zumindest teilweise, durch einige Anweisungen materialisiert, die die Dinge so einrichten, dass der richtige Wert, ob berechnet (zur Laufzeit) oder unmittelbar, richtig angesprochen wird.

Andere Tipps

Konstanten werden wahrscheinlich zur Kompilierungszeit vereinfacht, sodass Ihre Frage, wie sie buchstäblich gestellt werden, möglicherweise nicht helfen. Aber so etwas wie, sagen Sie, i - j + k Dies muss zur Laufzeit von einigen Variablen berechnet werden, kann je nach CPU -Architektur "gespeichert" werden, wo der Compiler mag: Der Compiler versucht normalerweise, das Beste zu tun, um Register zu verwenden, z. B.

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

Um einen solchen Ausdruck zu berechnen, um ihn in der ACCUMulator Register AX zu speichern, bevor Sie ihn einem Speicherort mit zuweisen STORE AX, dest oder dergleichen. Ich wäre ziemlich überrascht, wenn ein moderner Kompilierer in einer sogar halb anständigen CPU-Architektur (ja, x86 enthalten!-), um Register für einen angemessenen Ausdruck in das Gedächtnis zu verschütten!

This is compiler dependent. Usually the value (12) will be calculated by the compiler. It is then stored in the code, typically as part of a load/move immediate assembly instruction.

Where it stores it is actually totally up to the compiler. The standard does not dictate this behavior.

A typical place can be seen by actually compiling the code and looking at the assembler output:

int main (int argc, char *argv[]) {
    int a;
    a = 10 + 5 - 3;
    return 0;
}

which produces:

        .file   "qq.c"
        .def    ___main;
            .scl    2;
            .type   32;
        .endef
        .text
.globl _main
        .def    _main;
            .scl    2;
            .type   32;
        .endef
_main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        andl    $-16, %esp
        movl    $0, %eax
        addl    $15, %eax
        addl    $15, %eax
        shrl    $4, %eax
        sall    $4, %eax
        movl    %eax, -8(%ebp)
        movl    -8(%ebp), %eax
        call    __alloca
        call    ___main
        movl    $12, -4(%ebp)         ;*****
        movl    $0, %eax
        leave
        ret

The relevant bit is marked ;***** and you can see that the value is created by the compiler and just inserted directly into a mov type instruction.

Note that it's only this simple because the expression is a constant value. As soon as you introduce non-constant values (like variables), the code becomes a little more complicated. That's because you have to look those variables up in memory (or they may already be in a register) and then manipulate the values at run-time, not compile-time.

As to how the compiler calculates what the value should be, that's to do with expression evaluation and is a whole other question :-)

  • The result of the computation in the RHS (right-hand-side) is computed by the compiler in a step that's called "constant propagation".
  • Then, it is stored as an operand of the assembly instruction moving the value into a

Here's a disassembly from MSVC:

  int a;
  a = 10 + 5 - 3;

0041338E  mov         dword ptr [a],0Ch 

Your question is based on an incorrect premise.

The defining property of lvalue in C is that it has a place in storage, i.e it is stored. This is what differentiates lvalue from rvalue. Rvalue is not stored anywhere. That's what makes it an rvalue. If it were stored, it would be lvalue by definition.

The terms "lvalue" and "rvalue" are used to bisect the world of expressions. That is, (10+5-3) is an expression that happens to be an rvalue (because you cannot apply the & operator to it -- in C++ the rules are more complicated). At runtime, there are no expressions, lvalues or rvalues. In particular, they aren't stored anywhere.

You were wondering where the value 12 was stored, but the value 12 is neither an lvalue nor an rvalue (as opposed to the expression 12 which would be an rvalue, but 12 does not appear in your program).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top