VP Developer

Memory

published: 2026-04-08

O que é memória?

Imagine a memoria como um gigante array de bytes. Cada "gaveta" dessa array tem um índice, que chamamos de endereço (address, em inglês).

Memory

Variáveis: São apenas nomes légiveis que apontam para um desses endereços. Em vez de decorar o endereço 0xfff8 você usa o nome age.
  • Operador & (Address-of): Esse operador permite que você pergunta ao C: "Em qul gaveta da memória esta variavél está guardada?"
  • Exibição(%p): Usamos o especificador %p no printf para exibir esse endereço, geralmente em formato hexadecimal.

Isso é base para os famosos pointers

Exemplo de código

#include <stdio.h>
int main(){
	float temperature = 36.5;
	//Imprime o valor e o endereço exato na memória
	printf("Valor da variável: %.1f\n", temperature);
	printf("Endereço de memória (índice array): %p\n", (void*)&temperature);
	return 0
}

O que é endereço?

Um endereço de memória nada mais é do que um número! Pense nele com o índice exato de uma "gaveta" no grande array que é a memória do seu computador.

memory address

  • Apenas um número: Apesar de não parecer uma "casa", o endereço é um identificador numérico único para cada byte.
  • Hexadecimal (Base 16): Usamos formatos como 0xfff8 porque é o padrão da computação, mas ele representa um valor real (neste caso, 65.528).
  • Legibilidade: O hexadecimal ajuda a organizar endereços grandes de uma forma que faz mais sentido para o hardware e compiladores.
#include <stdio.h>
int main() {
	int value = 100;
	// %p exibe o número em hexadecimal (ex: 0x7ffd...)
	printf("Endereço (Hexadecimal): %p\n", (void*)&value);
	// Podemos ver o mesmo número "cru" em decimal
	printf("Enderecço (Decimal): %lu\n", ( unsigned long)&value);
	return 0;
}

Memória Virtual

  • Camada de Abstração: Seu programa não acessa os pentes de RAM físico diretamente. O Sistema Opereacional (OS, OPERATING SYSTEM) cria a Memória Virtual, fazendo o programa acreditar que tem acesso exclusivo a um bloco contínuo de memória.

memory virtual

  • Segurança e Isolamento: Essa técnica impede que um processo acesse ou corrompa os dados de outro programa, garantindo estabilidade ao sistema.
  • Simplicidade e Performance: O desenvolvedor não precisa gerenciar o hardware físico, e o OS pode otimizar o uso da RAM movendo dados para o disco se necessário.
  • Sistemas Embarcados: A única grande exceção é quando você programa firmware para dispositivos simploes sem OS; neles, o acesso à memória física costuma ser direto.

No fim, para o seu código C, a memória virtual continua sendo aquele grande "array de bytes" onde cada posição tem um endereço número.

Pointers

  • O Que é: Um ponteiro é apneas uma variável que armazena um memory address.
  • Por que o nome? Ele é chamado assim porque "aponta" para o local onde o dado real está guardado.
  • Sintaxe de Declaração: Usamos um asterisco (*) após o tipo de declaração para indicar que é um ponteiro (ex. int *).
  • Atribuição: Usamos o operador & (address-of) para pegar o endereço de uma variável comum e salvá-lo no ponteiro.
int age = 37;
int *pointer_to_age = &age; // O ponteiro agora guardad o endereço de 'idade'
  • Modificação Direta: Por padrão, o C copia dos dados ao passá-los para uma função (passagem por valor). Se você alterar a cópia dentro da função a variável original permanece igual. Com ponteiros, você passa o endereço e altera o dado original
  • Eficiência: Imagine uma struct com milhares de campos. Copiar tudo isso para cada função consumiriar muita memória e tempo. Passar apenas o endereço (pointer) é extremamente rápido e leve.

Em resumo, ponteiros dão às suas funções o "endereço da casa" em vez de uma "cópia da casa".

Pointer Basics

Os ponteiros funcionam como endereços residencias; eles não são o dado em si, mas indicam exatamente onde a inforrmação está guardada na memória. Para começar, você declara um ponteiro usando o simbolo de asterisco após o tipo e utiliza o operador & para capturar o endereço de uma variável específica.

A grande novidade aqui é a desreferenciação, que usa o mesmo asterisco para "entrar"no endereço e acessar ou modificar o valor real ali armazenado.

É essencial não confundir o uso do asterisco na declaração do tipo com o seu uso na manipulação dos dados, pois essa técnica permite que você altere o conteúdo original de uma variável diretamente, sem precisar criar cópias desnecessárias, o que torna o seu código muito mais eficiente e poderoso

#include <stdio.h>
int main() {
	int numero = 10;
	int *ptr = &numero; // Declaração: ptr é um ponteiro para int
	printf("Valor original: %d\n", numero);
	printf("Endereço armazenado: %\n";, (void*)ptr);
	// Desreferenciando para ler o valor
	printf("Acessando valor pelo ponteiro: %d\n", * ptr);
	// Desreferenciando para modificar o valor original
	*ptr = 20;
	printf("Novo valor de 'numero': %d\n", numero);
	return 0;
}

O segredo é lembrar que o * tem duas personalidades: na declaração, ele cria o ponteiro; no uso direto, ele serve para acessar o conteúdo dentro do endereço.

Pointers to Stucts

  • Ponto vs. Seta: Use (.) para acessar campos de structs comuns e -> quando tiver um ponteiro para struct.
  • Atalho elegeante: O comandoponteiro->campo é uma forma simplificada de escrever (*ponteior).campo.
  • Prioridade: Como o operador . tem maior precedência que o *, usar a seta evita a necessidade de parantêses confusos, tornando o códgico muti mais limpo.
#include <stdio.h>
typedef struct {
	int x;
	int y;
} ponto_t;
int main() {
	ponto_t p1 {10, 20};
	ponto_t *ptr = &p1;
	// Usando a seta para ler e modificar
	printf("X inicial: %d\n", ptr->x);
	ptr->x = 100; 
	prtinf("X atualziado: %d\n", p1.x);
	return 0;
}