Domanda

in C, ho questo pezzo di codice:

int a;
a = 10 + 5 - 3

Vorrei chiedere: dove è (10 + 5-3) conservato a? (Per quanto ne so, a si trova sulla pila, come su (10+5-3)? Come funziona questo rvalue ottenere calcolato?)

È stato utile?

Soluzione

In genere, il valore r viene "immagazzinata" all'interno del programma stesso.

In altre parole, il compilatore stesso ( prima che il programma sia mai eseguito ) calcola il 10 + 5 - valore 3 (può farlo in quanto dal momento che è tutto basato su valori immediati costanti), ed emette il codice assembly per memorizzare il risultato di questo calcolo in qualunque l-value per l'assegnazione (in questo caso, la variabile denominata a, che il compilatore probabilmente conosce come un indirizzo relativo ad un'origine segmento di dati di sorta).

Il valore di R, che ha un valore di 12 viene quindi trovata solo all'interno del binario del programma, all'interno di un'istruzione assembly che aspetto come

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

$ 0C è la "r-value".

Se il valore r è sembrato essere il risultato di un calcolo che può fare solo in fase di esecuzione, per esempio se il codice c sottostante era: a = 17 * x; // x qualche fase di esecuzione var, il valore r sarebbe troppo essere "memorizzato" (o meglio, materializzato) come una serie di istruzioni all'interno del binario programma. La differenza con la semplice "mov dest, imm" di cui sopra è che ci vorrebbero molte istruzioni per caricare variabile x in un accumulatore, moltiplicare per 17 e memorizzare il risultato all'indirizzo dove la variabile a è. E 'possibile che il compilatore può "autorizzare la stessa" ;-) di utilizzare lo stack per qualche risultato ecc intermedio ma tale sarebbe
a) completamente compilatore
dipendente b) transiant
c) e in genere comporterebbe solo parte del valore r
è quindi giusto dire che il valore R è un concetto fase di compilazione che è incapsulato in parti del programma (non i dati), e non è memorizzato ovunque ma nel binario programma.

In risposta a paxdiablo: la spiegazione offerta di cui sopra è davvero restrittiva delle possibilità perché lo standard c fa in modo efficace non dettare qualcosa del genere. Mai il, la maggior parte qualsiasi valore r meno è finalmente materializzato, almeno in parte, da alcune istruzioni che definisce le cose in modo che il valore corretto, se calcolato (in fase di esecuzione) o immediato viene affrontato in modo corretto.

Altri suggerimenti

Le costanti sono probabilmente semplificate al momento della compilazione, in modo che le domanda come letteralmente posta non può aiutare. Ma qualcosa come, ad esempio, i - j + k che ha bisogno di essere calcolato in fase di esecuzione da alcune variabili, possono essere "memorizzato" ovunque il compilatore piace, a seconda della architettura della CPU: il compilatore in genere cercare di fare del suo meglio per utilizzare i registri, ad esempio

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

per calcolare una tale espressione "memorizzare" nel registro accumulatore AX, prima di assegnare a qualche posizione di memoria con STORE AX, dest o simili. Sarei abbastanza sorpreso se un moderno compilatore ottimizzato su un'architettura anche semi-decente CPU (sì, 86 inclusa -!)! Necessari per versare i registri di memoria per qualsiasi ragionevolmente semplice espressione

Questa è compilatore dipendente. Solitamente il valore (12) viene calcolato dal compilatore. Esso viene quindi memorizzato nel codice, tipicamente come parte di un carico / spostare istruzioni di montaggio immediato.

Dove si memorizza in realtà è totalmente fino al compilatore. Lo standard non dettare questo comportamento.

A tipico posto può essere visto dal fatto compilare il codice e guardando l'output assembler:

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

che produce:

        .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

Il bit corrispondente è segnata ;***** e si può vedere che il valore è stato creato dal compilatore e appena inserito direttamente in un'istruzione di tipo mov.

Si noti che è solo questa semplice perché l'espressione è un valore costante. Non appena si introduce valori non costanti (come le variabili), il codice diventa un po 'più complicato. Questo perché si deve guardare le variabili in memoria (o possono essere già in un registro) e poi manipolare i valori a run-time , non a tempo di compilazione .

Per quanto riguarda come il compilatore calcola quale sia il valore dovrebbe essere, questo è a che fare con la valutazione di espressione ed è tutta un'altra domanda: -)

  • Il risultato del calcolo nella RHS (destra-lato) viene calcolato dal compilatore in un passo che si chiama "costante di propagazione".
  • Poi, viene memorizzato come operando dell'istruzione gruppo mobile il valore in a

Ecco un disassemblaggio da MSVC:

  int a;
  a = 10 + 5 - 3;

0041338E  mov         dword ptr [a],0Ch 

La tua domanda è basata su una premessa errata.

La proprietà che definisce Ivalue in C è che ha un posto in deposito, cioè è memorizzato . Questo è ciò che differenzia lvalue da rvalue . Rvalue è non memorizzati da nessuna parte. Questo è ciò che lo rende un rvalue. Se fosse conservato, sarebbe lvalue per definizione.

I termini "lvalue" e "rvalue" sono usati per tagliare in due il mondo delle espressioni. Cioè, (10+5-3) è un'espressione che sembra essere un rvalue (perché non si può applicare l'operatore & per esso - in C ++ le regole sono più complicate). In fase di esecuzione, non ci sono espressioni, lvalue o rvalues. In particolare, essi non vengono memorizzati da nessuna parte.

sono state chiedendo dove il valore 12 è stato memorizzato, ma il valore di 12 non è né un lvalue né un rvalue (in contrasto con la 12 espressione che sarebbe un rvalue, ma 12 non appare nel programma).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top