Para entender isso totalmente , você deve compreender os seguintes conceitos:
Arrays não são ponteiros!
Em primeiro lugar (e tem sido pregado o suficiente), matrizes não são ponteiros . Em vez disso, na maioria dos usos, eles 'decaem' para o endereço de seu primeiro elemento, que pode ser atribuído a um ponteiro:
int a[] = {1, 2, 3};
int *p = a; // p now points to a[0]
Presumo que funcione dessa forma para que o conteúdo do array possa ser acessado sem copiar todos eles. Isso é apenas um comportamento de tipos de array e não significa que eles sejam a mesma coisa.
Matrizes multidimensionais
Arrays multidimensionais são apenas uma forma de 'particionar' a memória de uma forma que o compilador / máquina possa entender e operar.
Por exemplo, int a[4][3][5]
= uma matriz contendo 4 * 3 * 5 (60) 'pedaços' de memória de tamanho inteiro.
A vantagem sobre o uso do int a[4][3][5]
vs plain int b[60]
é que agora eles estão 'particionados' (mais fácil de trabalhar com seus 'pedaços', se necessário), e o programa agora pode realizar a verificação vinculada.
Na verdade, int a[4][3][5]
é armazenado exatamente como int b[60]
na memória - A única diferença é que o programa agora o gerencia como se fossem entidades separadas de certos tamanhos (especificamente, quatro grupos de três grupos de cinco).
Lembre-se: int a[4][3][5]
e int b[60]
são iguais na memória, e a única diferença é como são tratados pelo aplicativo / compilador
{
{1, 2, 3, 4, 5}
{6, 7, 8, 9, 10}
{11, 12, 13, 14, 15}
}
{
{16, 17, 18, 19, 20}
{21, 22, 23, 24, 25}
{26, 27, 28, 29, 30}
}
{
{31, 32, 33, 34, 35}
{36, 37, 38, 39, 40}
{41, 42, 43, 44, 45}
}
{
{46, 47, 48, 49, 50}
{51, 52, 53, 54, 55}
{56, 57, 58, 59, 60}
}
A partir disso, você pode ver claramente que cada "partição" é apenas um array que o programa controla.
Sintaxe
Agora, os arrays são sintaticamente diferentes dos ponteiros . Especificamente, isso significa que o compilador / máquina os tratará de maneira diferente. Isso pode parecer óbvio, mas dê uma olhada nisto:
int a[3][3];
printf("%p %p", a, a[0]);
O exemplo acima imprime o mesmo endereço de memória duas vezes, assim:
0x7eb5a3b4 0x7eb5a3b4
No entanto, apenas um pode ser atribuído a um ponteiro de forma tão direta :
int *p1 = a[0]; // RIGHT !
int *p2 = a; // WRONG !
Por que não pode a
ser atribuído a um ponteiro, mas a[0]
pode?
Isso, simplesmente, é uma consequência de matrizes multidimensionais, e vou explicar por quê:
No nível de ' a
', ainda vemos que temos outra 'dimensão' pela qual esperar. No nível de ' a[0]
', entretanto, já estamos na dimensão superior, portanto, no que diz respeito ao programa, estamos apenas olhando para um array normal.
Você pode estar perguntando:
Por que é importante se o array é multidimensional em relação a fazer um ponteiro para ele?
É melhor pensar assim:
Um 'decaimento' de um array multidimensional não é apenas um endereço, mas um endereço com dados de partição (também conhecido como ele ainda entende que seus dados subjacentes são feitos de outros arrays), que consiste em limites definidos pelo array além da primeira dimensão.
Esta lógica de 'partição' não pode existir dentro de um ponteiro, a menos que o especifiquemos:
int a[4][5][95][8];
int (*p)[5][95][8];
p = a; // p = *a[0] // p = a+0
Caso contrário, o significado das propriedades de classificação da matriz será perdido.
Observe também o uso de parênteses em torno de *p
: int (*p)[5][95][8]
- Isso é para especificar que estamos fazendo um ponteiro com esses limites, não uma matriz de ponteiros com esses limites:int *p[5][95][8]
Conclusão
Vamos revisar:
- Matrizes decaem para endereços se não tiverem outra finalidade no contexto usado
- Matrizes multidimensionais são apenas matrizes de matrizes - Portanto, o endereço 'decadente' carregará o fardo de "Eu tenho subdimensões"
- Os dados de dimensão não podem existir em um ponteiro, a menos que você os forneça .
Em resumo: arrays multidimensionais decaem para endereços que carregam a capacidade de entender seus conteúdos.