Revise as aulas 34 a 42 com uma folha de consulta, seis questões de leitura de código e uma lista de erros frequentes.
int x = 5; int *p = &x; // p guarda o endereço de x printf("%d\n", *p); // 5 (lê o conteúdo) *p = 100; // x também passa a 100!
int *p, * faz parte da declaração do ponteiro. Em *p = 5, * desreferencia o ponteiro.struct Point { int x, y; }; struct Point p = { 3, 4 }; printf("%d %d\n", p.x, p.y); // 3 4 struct Point *pp = &p; printf("%d\n", pp->x); // 3 (-> equivale a (*pp).x)
.; com um ponteiro, use ->#include <stdlib.h> int *a = malloc(sizeof(int) * 10); if (a == NULL) { /* Falha */ } a[0] = 42; free(a); // Libere a memória! a = NULL; // Evita liberar novamente por este ponteiro
NULL é retornadoFILE *fp = fopen("data.txt", "r"); if (fp == NULL) { /* Não foi possível abrir */ } int n; fscanf(fp, "%d", &n); fclose(fp); // Feche o arquivo!
| Símbolo | Significado | Exemplo |
|---|---|---|
| & | AND | 5 & 3 → 1 |
| | | OR | 5 | 3 → 7 |
| ^ | XOR | 5 ^ 3 → 6 |
| ~ | Inversão | ~5 → -6 |
| << | Deslocamento à esquerda | 1 << 3 → 8 |
| >> | Deslocamento à direita | 8 >> 2 → 2 |
(n & 1) == 0n << 1 / n >> 1&& e operadores de bits & têm funções diferentesint x = 10; int *p = &x; *p = 99; printf("%d\n", x);
p = &x faz p apontar para x. *p = 99 grava 99 no objeto apontado, que é x. Portanto, x passa a 99. Ponteiros permitem modificar variáveis de quem chama a função, o que exige cuidado.void swap(int *a, int *b) { int t = *a; *a = *b; *b = t; } int x = 3, y = 7; swap(&x, &y); printf("%d %d\n", x, y);
t = *a guarda 3; depois, *a = *b coloca 7 em x; por fim, *b = t coloca 3 em y. A saída é 7 3. Trocar somente cópias locais não alteraria as variáveis originais.struct Point { int x, y; }; struct Point p = {10, 20}; struct Point *pp = &p; pp->x = 99; printf("%d %d\n", p.x, p.y);
pp->x equivale a (*pp).x e acessa o membro x da estrutura p. Portanto, pp->x = 99 modifica p.x. O membro y permanece 20, e a saída é 99 20. O operador -> acessa membros de uma estrutura por meio de um ponteiro.#include <stdlib.h> int *a = malloc(sizeof(int) * 3); a[0] = 10; a[1] = 20; a[2] = 30; int sum = a[0] + a[1] + a[2]; free(a); printf("%d\n", sum);
free. Liberar o bloco alocado não apaga sum, que é uma variável local independente. A saída é 60. Se o programa tentasse ler a[0] depois de free, haveria comportamento indefinido: use-after-free.for (int n = 1; n <= 5; n++) { if ((n & 1) == 0) printf("%d ", n); }
n & 1 extrai o bit menos significativo: zero para pares e um para ímpares. Logo, (n & 1) == 0 é verdadeiro para pares. Entre 1 e 5, isso ocorre com 2 e 4, produzindo 2 4. O teste n % 2 == 0 expressa a mesma ideia; o desempenho depende das otimizações.struct P { int x, y; }; struct P a = {1, 2}; struct P b = a; // Cópia b.x = 99; printf("%d %d %d %d\n", a.x, a.y, b.x, b.y);
struct P b = a faz uma cópia por valor da estrutura inteira. a e b são objetos independentes, então alterar b.x não altera a.x. A saída é 1 2 99 2. Estruturas que contêm ponteiros exigem atenção à cópia superficial; neste exemplo, os membros são int.int *p; *p = 5; usa um endereço indeterminado → comportamento indefinido. Inicialize com NULL ou com um endereço válido.
p = NULL após free ajuda a evitar reutilizar esse ponteiro.if(fp == NULL) .
p.x; com um ponteiro, use pp->x. Escrever pp.x quando pp é um ponteiro causa erro de compilação.&& e operadores de bits & por engano(a == 1) & (b == 2) combina bits dos resultados das comparações, mas não faz curto-circuito, podendo mudar os efeitos colaterais. Para condições, use &&.
& e * Para revisar o significado
Quiz (Ponteiros)Pratique com questões semelhantes
Structs (struct)Para revisar o acesso a membros (. e ->)
Aula 40: Uniões (union)Para revisar o compartilhamento de memória
Aula 41: Entrada/Saída de arquivosPara revisar fopen, fclose e modos de abertura
Aula 42: Memória dinâmicaPara revisar malloc, free e verificação de NULL
Operadores Bit a BitPara revisar deslocamentos, AND, OR e XOR
Folha de consulta rápidaRevise ponteiros, estruturas e malloc em uma página