Entendendo sizeof em C++: Por que n não é igual a 8?

Ao trabalhar com arrays em C++, você pode encontrar resultados inesperados relacionados ao operador sizeof, especialmente ao passar arrays para funções. Neste post do blog, exploraremos uma confusão comum que surge ao usar sizeof com parâmetros de função, respondendo particularmente à pergunta: Por que n não é igual a 8 na função foo()?

O Problema

Vamos examinar dois trechos de código que ilustram a questão:

Exemplo 1: Função foo()

void foo(char cvalue[8])
{
    int n = sizeof(cvalue);
}

No exemplo acima, quando chamamos sizeof(cvalue), pode-se esperar que n seja igual a 8, já que o array é definido com um tamanho de 8. No entanto, este não é o caso.

Exemplo 2: Função bar()

void bar()
{
    char cvalue[8];
    int n = sizeof(cvalue);
}

Neste segundo exemplo, sizeof(cvalue) é igual a 8. Então, por que a diferença?

Entendendo o Conceito

Para entender por que sizeof(cvalue) retorna valores diferentes em cada função, precisamos esclarecer como os arrays são tratados em C e C++.

Arrays como Parâmetros de Função

Quando você passa um array para uma função em C ou C++, na verdade não está passando o array em si. Em vez disso, o que está sendo passado é um ponteiro para o primeiro elemento do array. Os colchetes usados nos parâmetros da função são apenas uma notação sintática, que não muda o comportamento—todas as seguintes declarações são equivalentes:

  • void foo(char cvalue[8])
  • void foo(char cvalue[])
  • void foo(char *cvalue)

Em todas essas declarações, cvalue é interpretado como um ponteiro. Assim, quando você chama sizeof(cvalue) dentro de foo(), ele retorna o tamanho do ponteiro, e não o tamanho do array. Na maioria das plataformas, esse tamanho é tipicamente 4 bytes em um sistema de 32 bits e 8 bytes em um sistema de 64 bits, razão pela qual n não é igual a 8 em foo().

O Contexto Correto em bar()

Em contraste, dentro de bar(), cvalue é definido como um array local de tamanho 8. Portanto, quando sizeof(cvalue) é invocado aqui, ele reflete corretamente o tamanho do array inteiro, resultando em n igual a 8.

Principais Conclusões

  • Entendendo o Comportamento de Ponteiros: Ao passar arrays como parâmetros, você está na verdade passando um ponteiro, o que pode levar a valores enganadores ao usar sizeof.
  • Arrays Locais: sizeof fornece o tamanho real de arrays locais definidos dentro de uma função, resultando na saída esperada.
  • Açúcar Sintático: Os colchetes nos parâmetros de função não criam variáveis de array, mas indicam que você está lidando com um ponteiro.

Conclusão

Lidar com arrays em C e C++ pode ser complicado, especialmente para quem é novo na linguagem. Compreender a distinção entre ponteiros e arrays é crucial para cálculos e depuração precisos. Lembre-se de que, ao estar dentro de uma função, sizeof aplicado a um parâmetro suposto ser um array fornece o tamanho do ponteiro, e não o tamanho do array que você pretendia passar.

Esperamos que esta explicação ilumine o comportamento do operador sizeof em relação aos argumentos de array em funções, esclarecendo por que n não é igual a 8 na função foo(), mas é em bar(). Mantenha esses princípios em mente enquanto você codifica!