No Item2 na página 16, (Preferir consts, enumerações e linhas para #defines), Scott diz:
Além disso, embora bons compiladores não reservem armazenamento para objetos const de tipos inteiros ...
Eu não entendo isso. Se eu definir um objeto const, por exemplo,
const int myval = 5;
então certamente o compilador deve reservar um pouco de memória (de tamanho int) para armazenar o valor 5?
Ou os dados const são armazenados de alguma maneira especial?
Esta é mais uma questão de armazenamento do computador, suponho. Basicamente, como o computador armazena objetos const para que nenhum armazenamento seja reservado?
c++
computer-science
user619818
fonte
fonte
storage of const object
a fonte da sua pergunta tem pouco valor.Respostas:
Uma afirmação um pouco mais correta seria que os compiladores não reservariam memória de dados para objetos const do tipo inteiro: eles trocariam por memória de programa . Não há diferença entre os dois na arquitetura Von Neumann, mas em outras arquiteturas, como Harvard, a distinção é bastante importante.
Para entender completamente o que está acontecendo, é preciso lembrar como a linguagem assembly carrega dados para processamento. Existem duas maneiras fundamentais de carregar os dados - ler uma memória de um local específico (o chamado modo de endereçamento direto ) ou definir uma constante especificada como parte da própria instrução (o chamado modo de endereçamento imediato ). Quando o compilador vê uma
const int x = 5
declaração seguida porint a = x+x
, ele tem duas opções:x
for referenciado, gere uma instrução de carga imediata do valor 5No primeiro caso, você verá uma leitura
x
no registro do acumulador , uma adição do valor no local dox
acumulador e uma loja no local dea
. No segundo caso, você verá uma carga imediata de cinco, uma adição imediata de cinco, seguida por uma loja no local dea
. Alguns compiladores pode descobrir que você está adicionando uma constante para si, otimizara = x+x
paraa = 10
, e gerar uma única instrução que armazena dez no locala
.fonte
Não necessariamente. Também pode optar por usar apenas o valor bruto 5 em vez de
myval
no código compilado.A diferença entre
#define MYVAL 5
econst int myval = 5
é que, no primeiro caso, o compilador não tem escolha alguma, pois o pré-processador já substituiu todas as mençõesMYVAL
no código-fonte5
no momento em que o compilador vê o código-fonte. No último caso, porém, há uma escolha. Para uma compilação de depuração não otimizada, o compilador pode alocar explicitamente aconst int
, portanto, no depurador, você poderá ver a constantemyval
, em vez de apenas o valor bruto 5.fonte
O que a citação diz não é muito correto.
Um bom compilador não reservará armazenamento para variáveis const estáticas . Se a variável const não é estática e está no escopo do arquivo, ela deve reservar armazenamento, porque a variável pode ser referenciada a partir de outra unidade de compilação. Com as otimizações de tempo do link, o vinculador poderá eliminar o armazenamento e reescrever instruções que fazem referência à variável, se puder provar que o programa não gera um ponteiro para essa variável.
Uma razão muito melhor para usar, em
const int
vez de,#define
é que os depuradores não "veem" as macros; portanto, você não pode inspecionar um#defined
valor no depurador.fonte
Roubarei a primeira frase da resposta de Péter Török, mas elaborarei de maneira diferente: não necessariamente. Também pode optar por usar apenas o valor bruto 5 em vez de
myval
no código compilado.Tratar
myval
como uma variável regular alocando espaço para ela na memória pode ter implicações de desempenho que variam de minúsculas a severas, dependendo da arquitetura e de como ela lida com a memória.Trabalhando dessa maneira, um compilador emitirá uma instrução que diz algo como "carregar o registrador R com o que estiver no local da memória
myval
". A localização demyval
como um operando da instrução, ela sai diretamente do mesmo bloco de dados que a própria instrução. Em CPUs modernas, esse valor estará prontamente disponível no chip devido à pré-busca de instruções. Com o endereço em mãos, a CPU ainda precisa obter o valor da memória. Isso pode ocorrer rapidamente se o local estiver próximo no cache ou não tão rapidamente se não estiver. Não apenas a CPU precisa sair do chip para obter o valor, como pode forçá-la a extrair outros dados mais úteis do cache que precisarão ser trazidos mais tarde. Quando o programa está sendo executado em um sistema operacional que virtualiza a memória, o acesso a esse local pode causar uma falha na página, resultando na suspensão do programa até que a página necessária seja trazida para a RAM via E / S periférica (por exemplo, disco),Ao conectar o valor constante ao código do objeto, o compilador emitirá uma instrução como "load register R with the value
5
". Como o endereço de memória descrito acima,5
seria um operando para a instrução e disponível da mesma maneira (ou seja, pré-buscado). É aí que a semelhança termina, porque a CPU agora tem tudo o que precisa para colocar o5
registro R e continuar com seus negócios. Como endereços e registradores geralmente têm o mesmo tamanho, não há diferença no número de bytes que a instrução ocupa e a execução real ocorre com zero chances de erros de cache e falhas de página que podem ocorrer quando você retira algo da memória.O compilador pode, como Péter apontou, alocar espaço e um símbolo para
myval
compilações de depuração. Não haveria nenhum mal em fazer isso e ainda manter a fiação do seu valor, já que o valor permanece o mesmo, não importa o quê e o símbolo esteja realmente lá para nós, humanos, usarmos na depuração.Observe que isso se aplica apenas a valores que podem ser mantidos em registros, porque os registros são números inteiros por natureza. Outras constantes acabarão na memória.
fonte
O compilador substituirá o número cinco sempre que a variável 'myval' for usada.
fonte
O compilador pode considerar valores const como operandos imediatos. Operandos imediatos não requerem armazenamento de dados. O compilador pode tratar:
o mesmo que
O valor 5 não é armazenado na memória de dados, mas como parte da sequência de instruções.
O compilador deve reservar armazenamento de dados nos casos em que o endereço de um valor possa ser obtido. Mesmo nesse caso, o compilador ainda usará operações imediatas quando o valor de myVal for usado.
fonte