Pergunta

em C, eu tenho este trecho de código:

int a;
a = 10 + 5 - 3

Eu quero perguntar:onde (10+5-3) está armazenado?(Até onde sei, a está localizado na pilha, que tal (10+5-3)?Como esse valor é calculado?)

Foi útil?

Solução

Normalmente, o valor R é "armazenado" dentro do próprio programa.

Em outras palavras, o próprio compilador (antes do programa ser executado) calcula o valor 10 + 5 - 3 (pode fazê -lo, pois tudo é baseado em valores imediatos constantes) e emite o código de montagem para armazenar o resultado desse cálculo em qualquer valor L para a atribuição (neste Caso, a variável chamada A, que o compilador provavelmente conhece como um endereço relativo para uma espécie de origem do segmento de dados).

O valor R, que tem um valor de 12, só é encontrado dentro do binário do programa, dentro de uma instrução de montagem que parece Curti

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

$ 0c é o "Valor R".

Se o valor R for o resultado de um cálculo que só pode ser feito em tempo de execução, digamos se o código C subjacente foi: a = 17 * x; // x algum tempo de execução VAR, o valor R também seria "armazenado" (ou melhor, materializado) como uma série de instruções no binário do programa. A diferença com o simples "mov dest, imm" acima é que foram necessárias várias instruções para carregar a variável x em um acumulador, multiplicar por 17 e armazenar o resultado no endereço em que a variável A é. É possível que o compilador possa "autorizar-se" ;-) para usar a pilha para algum resultado intermediário etc. mas isso seria
a) completamente dependente do compilador
b) transiant
c) e normalmente só envolveria papel do valor R.
Portanto, é seguro dizer que o valor R é um conceito de tempo de compilação que é encapsulado em partes do programa (não nos dados) e não é armazenado em nenhum lugar, mas no binário do programa.

Em resposta a paxdiablo: a explicação oferecida acima é de fato restritiva das possibilidades porque o padrão C efetivamente faz não ditar qualquer coisa dessa natureza. No entanto, quase qualquer valor R é materializado, pelo menos em parte, por algumas instruções que definem as coisas para que o valor adequado, calculado (no tempo de execução) ou imediato seja abordado corretamente.

Outras dicas

As constantes provavelmente são simplificadas no momento da compilação, portanto, sua pergunta como literalmente feita pode não ajudar. Mas algo como, digamos, i - j + k Isso precisa ser calculado em tempo de execução de algumas variáveis, pode ser "armazenado" onde quer que o compilador goste, dependendo da arquitetura da CPU: o compilador normalmente tentará fazer o possível para usar registros, por exemplo,

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

Para calcular essa expressão "armazenando" no AX do registro do acumulador, antes de atribuí -lo a algum local de memória com STORE AX, dest ou semelhante. Eu ficaria bastante surpreso se um compilador de otimização moderno em uma arquitetura de CPU semi-decentada (sim, x86 incluída!-) precisava derramar registros para a memória para qualquer expressão razoavelmente simples!

Isso depende do compilador. Normalmente, o valor (12) será calculado pelo compilador. Em seguida, é armazenado no código, normalmente como parte de uma instrução de montagem imediata de carga/movimentação.

Onde ele armazena é na verdade totalmente até o compilador.O padrão não determina esse comportamento.

A típica lugar pode ser visto compilando o código e observando a saída do assembler:

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

que produz:

        .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

O bit relevante é marcado ;***** e você pode ver que o valor é criado pelo compilador e apenas inserido diretamente em um mov digite instrução.

Observe que é simples assim porque a expressão é um valor constante.Assim que você introduz valores não constantes (como variáveis), o código se torna um pouco mais complicado.Isso porque você tem que procurar essas variáveis ​​na memória (ou elas já podem estar em um registrador) e então manipular os valores em tempo de execução, não tempo de compilação.

Quanto à forma como o compilador calcula qual deve ser o valor, isso tem a ver com a avaliação da expressão e é uma outra questão :-)

  • O resultado do cálculo no RHS (do lado direito) é calculado pelo compilador em uma etapa chamada "propagação constante".
  • Em seguida, é armazenado como um operando da instrução de montagem, movendo o valor para a

Aqui está uma desmontagem do MSVC:

  int a;
  a = 10 + 5 - 3;

0041338E  mov         dword ptr [a],0Ch 

Sua pergunta é baseada em uma premissa incorreta.

A propriedade definidora de lvalue em c é que ele tem um lugar em armazenamento, ou seja, é armazenado. É isso que diferencia LValue de rvalue. Rvalue é não armazenado em qualquer lugar. É isso que o torna um Rvalue. Se fosse armazenado, seria lvalue por definição.

Os termos "lvalue" e "rvalue" são usados ​​para dividir o mundo das expressões.Aquilo é, (10+5-3) é uma expressão que é um rvalue (porque você não pode aplicar o operador & a ela - em C++ as regras são mais complicadas).Em tempo de execução, não há expressões, lvalues ​​ou rvalues.Em particular, eles não são armazenados em lugar nenhum.

Você estava se perguntando onde o valor 12 foi armazenado, mas o valor 12 não é um lvalue nem um rvalue (ao contrário da expressão 12 o que seria um rvalue, mas 12 não aparece no seu programa).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top