C torna arrays e ponteiros inseparáveis. Você não pode escrever um código eficaz sem compreender o relacionamento deles. Leva tempo para dominar. A recompensa é o controle imediato sobre a memória.
Considere uma configuração básica. Você declara duas matrizes inteiras de tamanho dez.
Compile isso. Ele falha. Você não pode atribuir um array a outro usando o sinal de igual. C não oferece suporte à cópia em massa por meio de operadores de atribuição. Para copiar a em b, você deve percorrer cada elemento.
Você poderia compactar esse loop em uma única linha com um operador de vírgula, mas a legibilidade é prejudicada. A abordagem padrão é usar memcpy de string.h. Ele lida com a cópia em nível de byte com eficiência.
A falha de b=a revela uma regra fundamental. Em C, variáveis de array não são arrays. Eles são ponteiros fixos. a e b são identificadores permanentes para o endereço inicial de seus respectivos blocos de memória. a aponta para a[0]. b aponta para b[0]. Esses endereços são imutáveis. Você não pode redirecionar um nome de variável para um local de memória diferente. É por isso que a atribuição falha. O compilador trata o nome do array como um ponteiro constante.
Como o nome é efetivamente um ponteiro, você pode usar aritmética de ponteiro para acessar dados. É aqui que a sintaxe se torna poderosa.
Aqui, p é uma variável de ponteiro. Você pode atribuir o endereço da matriz a a p. A instrução p=a copia o endereço. Agora p contém o mesmo valor que o nome do array a. Desreferenciar p com *p recupera o primeiro elemento. A saída é zero.
Essa distinção é importante porque variáveis de ponteiro podem ser alteradas. Você pode fazer p apontar para a[1] ou a[5] usando aritmética. O próprio nome do array permanece preso no início. Essa flexibilidade permite que funções iterem pela memória sem copiar grandes estruturas de dados. É a espinha dorsal do desempenho de baixo nível em C.
Compreender este link evita erros sutis. Explica por que algumas funções aceitam ponteiros em vez de sintaxe de array. Esclarece o layout da memória. Ignore-o e você enfrentará falhas de segmentação ou substituições não intencionais de dados. Aprenda e você verá exatamente o que a máquina está fazendo.
A sintaxe pode parecer pouco natural no início. O duplo sentido dos colchetes e asteriscos confunde os iniciantes. Mas uma vez que o modelo funciona, a abstração desaparece. Você fica com endereços e valores. Nada mais.
Vale a pena o esforço mental? O código fica mais rápido. O uso de memória cai. Você obtém acesso direto às operações em nível de hardware. A maioria dos programas C depende

Você pode atribuir uma variável de array diretamente a um ponteiro porque, nos bastidores, eles são essencialmente a mesma coisa.
p=a; funciona não por causa de mágica, mas porque a decai em um ponteiro. Especificamente, aponta para o endereço de memória do primeiro elemento do array (índice 0). Como esse elemento é um número inteiro, a atua como um ponteiro para um único int. Declarar p como um ponteiro inteiro e defini-lo igual a a é apenas permitir que duas variáveis compartilhem o mesmo endereço. Você poderia escrever p=&a[0]; em vez disso. O resultado é idêntico.
Depois que p estiver conectado ao início de a, você ganha mobilidade. Nomes de array como a são constantes; são endereços fixos que não podem ser alterados. Indicadores como p são diferentes. Você pode movê-los usando aritmética de ponteiro.
É aqui que C fica inteligente.
Quando você escreve p++;, o compilador não adiciona apenas um byte ao endereço. Ele sabe que p aponta para um número inteiro. Em vez disso, ele adiciona bytes sizeof(int), pousando exatamente no próximo elemento. Se p apontasse para uma estrutura de 100 bytes de comprimento, p++ avançaria 100 bytes. C cuida da matemática. Você apenas move o ponteiro.
Copiando arrays sem índices
Você pode copiar um array para outro usando esses ponteiros. Em vez de um loop padrão com índices:
Você pode usar ponteiros:
É detalhado. Você pode compactá-lo.
Ou recolha-o em uma única linha.
A precedência do operador aqui é fazer trabalho pesado. * tem precedência maior que ++, mas o pós-incremento acontece depois que o valor é obtido. Então *p++ busca o valor atual e então move o ponteiro. *q++ faz o mesmo para o destino. A tarefa acontece no meio. É compacto. É rápido. Também é fácil interpretar mal se você não estiver prestando atenção.
A zona de perigo
O que acontece se você pressionar p ou q além do final do array?
C não te impede.
O compilador assume que você sabe o que está fazendo. Ele continuará incrementando os ponteiros, copiando dados para a memória que não pertencem ao array. Você pode substituir outras variáveis. Você pode corromper a pilha. Você pode travar o programa mais tarde, em algum lugar não relacionado ao bug.
É por isso que a verificação de limites é manual em C. A linguagem confia em você. Quando você sai da linha, você paga o preço.
Passando Arrays para Funções
Você pode passar arrays para funções de duas maneiras. Eles parecem diferentes, mas se comportam de maneira semelhante.
Considere uma função que imprime um array:
Ou a versão do ponteiro:
O parâmetro nia (número no array) é obrigatório. Matrizes em C não carregam seu tamanho com elas. A função precisa saber quando parar.
Em ambos os casos, você está passando um ponteiro para o início do array, não







































