const int*, int * const, const int * const: Análise Sangrenta de Ponteiros

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: Por que este tópico enlouquece até mesmo desenvolvedores C++ experientes?

\n\n

Se você já abriu um código C++ de outra pessoa e viu algo como const int * const data, certamente sentiu vontade de fechar o editor e ir tomar um chá. Essa sintaxe estranha com const espalhado em ambos os lados do asterisco é uma verdadeira pedra no sapato. A pergunta «What is the difference between const int*, const int * const, and int * const?» no Stack Overflow acumulou centenas de milhares de visualizações. E isso não é por acaso.

\n\n

Entender essas construções não é apenas um capricho de pedante. É a chave para escrever código seguro, autodocumentado e, o que é importante, para passar em entrevistas. Hoje vamos acabar de vez com essa confusão, usando uma regra simples que funciona sempre.

\n\n

Os três pilares: o que vamos comparar?

\n\n

Em C++, ponteiros e constância podem se combinar de quatro maneiras (três delas são as mais populares). Vamos defini-las:

\n\n
    \n
  • Opção 1: const int* ptr (ou int const* ptr — é a mesma coisa).
  • \n
  • Opção 2: int * const ptr.
  • \n
  • Opção 3: const int * const ptr (combinação das duas primeiras).
  • \n
\n\n

A ideia chave: const sempre se refere ao que está à sua esquerda. Se não houver nada à esquerda, refere-se ao que está à direita. Parece simples, mas na prática essa regra salva.

\n\n

Opção 1: const int* ptr (Ponteiro para inteiro constante)

\n\n

Lendo da direita para a esquerda: «ptr é um ponteiro para um número inteiro que é constante».

\n\n

O que isso significa na prática?

\n
    \n
  • Você não pode alterar o valor da variável para a qual ptr aponta, através deste ponteiro.
  • \n
  • Você pode alterar o próprio ponteiro (fazê-lo apontar para outra variável).
  • \n
\n\n
#include <iostream>\n\nint main() {\n    int a = 10;\n    int b = 20;\n\n    const int* ptr = &a;  // ptr — ponteiro para const int\n\n    // *ptr = 15; // ERRO de compilação! Não é possível alterar o valor através de const int*\n    std::cout << "*ptr = " << *ptr << std::endl; // Exibirá 10\n\n    ptr = &b; // OK! Alteramos o próprio ponteiro\n    std::cout << "*ptr = " << *ptr << std::endl; // Exibirá 20\n\n    return 0;\n}
\n\n

Este tipo é frequentemente usado para passar dados para uma função, quando você quer garantir que a função não estrague os dados originais. Por exemplo, a string void print(const int* data) é uma promessa de "somente leitura".

\n\n

Opção 2: int * const ptr (Ponteiro constante para um número inteiro)

\n\n

Lendo da direita para a esquerda: «ptr é um ponteiro constante para um número inteiro».

\n\n

Aqui é o contrário:

\n
    \n
  • Você pode alterar o valor da variável para a qual ptr aponta.
  • \n
  • Você não pode alterar o próprio ponteiro (ele deve sempre apontar para a mesma área de memória).
  • \n
\n\n
#include <iostream>\n\nint main() {\n    int a = 10;\n    int b = 20;\n\n    int * const ptr = &a; // ptr — ponteiro constante para int\n\n    *ptr = 15; // OK! Alteramos o valor através do ponteiro\n    std::cout << "*ptr = " << *ptr << std::endl; // Exibirá 15\n\n    // ptr = &b; // ERRO de compilação! Não é possível alterar o próprio ponteiro\n\n    return 0;\n}
\n\n

Imagine que int * const é um ponteiro "fixo". Ele é frequentemente usado para trabalhar com registros de hardware ou em casos onde o ponteiro para um buffer não deve "fugir" para outro lugar.

\n\n

Opção 3: const int * const ptr (Ponteiro constante para um inteiro constante)

\n\n

Lendo da direita para a esquerda: «ptr é um ponteiro constante para um número inteiro, c

Blogs

Book Recommendations