Matrizes e ponteiros não são a mesma coisa em C, embora estejam relacionados e possam ser usados de maneira semelhante. Até agora todos concordamos.
No entanto, não vejo por que matrizes foram incluídas em C, quando ponteiros poderiam ter feito seu trabalho perfeitamente.
Não estou dizendo para remover a notação da matriz (por exemplo, a [5] ou int a [4] = {0,1,2,3};), o que é bastante útil e conveniente. Mas você pode ter essa mesma notação trabalhando em cima de ponteiros (como é o caso), como uma medida cosmética. Portanto, a notação de matriz não é um motivo para ter matrizes, apenas a notação!
A única diferença que vejo é que as matrizes são ponteiros constantes e o tamanho da memória para a qual elas apontam não pode ser alterado. Mas isso também pode ser alcançado com ponteiros, exatamente tornando-os constantes (a memória não seria de tamanho fixo, mas não tenho certeza se isso é um problema).
Então, por que não ter apenas ponteiros e deixar o programador decidir como o ponteiro deve se comportar (ou seja, constante, não constante, tamanho fixo, tamanho variável, etc)?
x = a + b * 2;
quando você pode obter o mesmo com uma sequência de expressões simples comox = b; x*=2; x+=a;
?Respostas:
Matrizes são memória contígua criada na pilha. Você não pode garantir memória de pilha contígua sem esse açúcar sintático e, mesmo que pudesse, teria que alocar um ponteiro separado para poder fazer a aritmética do ponteiro (a menos que você quisesse
*(&foo + x)
, o que eu não sou) claro, mas isso pode violar a semântica do valor-l, mas é pelo menos bastante estranho e gritaria por algum tipo de açúcar sintático). Em termos de design, também é uma forma de encapsulamento, já que você pode consultar a coleção com um único identificador (que de outra forma exigiria um ponteiro separado). E mesmo que você pudesse alocá-los de forma contígua e alocar um ponteiro separado para referenciá-los, você teriaint fooForSomething, fooForSomethingElse
... o que força uma quantidade razoável de criatividade à medida que sua coleção cresce, então você pode simplificar comint foo1, foo2
..., que se parece com uma matriz, mas é mais difícil de manter.fonte
static
) geralmente termina em outro lugar, dependendo do ambiente.A notação de matriz é conveniente, mais fácil de ler e menos propensa a erros. Ele fornece um formalismo sobre ponteiros. Pode ser açúcar sintático, mas todos precisamos de um pouco de doçura de vez em quando, não é?
Como em todas as abstrações, você abre um pouco de flexibilidade para a conveniência que a abstração oferece.
fonte
Estou surpreso que ninguém tenha comentado nada sobre matrizes multidimensionais ainda.
Se você possui uma matriz feita de "ponteiros aninhados" (digamos
int **p
), o que você tem em cada "linha" (dimensão externa) é um ponteiro que aponta para o primeiro elemento nessa linha, portanto, acessar um valor requer dois acessos à memória. Além disso, a memória necessária ésizeof(*int)*n + n*m*sizeof(int)
.No cenário de matriz bidimensional
int p[n][m]
, o acesso a um elemento requer apenas um acesso à memória, porque o endereço da linha é calculado em vez de procurado; e a memória necessária é justan*m*sizeof(int)
.Outro local onde uma matriz não pode ser substituída por um ponteiro é dentro das estruturas.
definitivamente não é o mesmo que
o tamanho da matriz é importante lá e os ponteiros não possuem essa informação.
Portanto, sim, matrizes unidimensionais e ponteiros únicos são basicamente intercambiáveis, mas suas semelhanças terminam aí.
fonte
i,j
pori*cols+j
, mas acho que não ter que fazer isso sozinho é um motivo bom o suficiente para justificar a existência de tipos de array.Por que eu gostaria de não conseguir usar matrizes para tipos de valor?
int a[4] = {0,1,2,3};
fonte
Como você lidaria com plataformas, como a 8031 sem memória externa, que não suportam
malloc
oualloca
? Talvez você esteja esquecendo que C não é apenas para grandes ferros, mas também para controladores de elevador e torradeiras.fonte
Em C, a notação de matriz dentro de expressões é sempre simplesmente aritmética de ponteiro. Todos os usos de um identificador de matriz em uma expressão são convertidos imediatamente de "matriz de T" para "ponteiro para T" e o valor é convertido em um ponteiro para o primeiro elemento da matriz. A notação da matriz (por exemplo
a[1][2]
) é sempre expandida para a aritmética do ponteiro (por exemplo*(*(t+1)+2)
).No entanto, a notação de matriz em declarações e definições é algo totalmente diferente. Uma matriz Declarador descreve uma "matriz de T tipo" onde os valores deste tipo são sequências de elementos de tipo T . Uma definição de um objeto de matriz tem tudo a ver com usar uma notação de matriz conveniente e fácil de entender para alocar a quantidade apropriada de armazenamento para a matriz de objetos desejada, de modo que o identificador da matriz se refira a esse armazenamento sem parecer um ponteiro. Com efeito, a notação de matriz em uma declaração ou definição é uma macro que gera uma expressão usando
sizeof()
e aritmética e, no caso de uma definição, o equivalente aalloca()
para matrizes automáticas ou seu equivalente no vinculador para matrizes globais e fazer tudo isso em tempo de compilação (exceto, por exemplo, matrizes de tamanho variável C99).O uso de notação de matriz em expressões e o uso de tipos de matriz não são tão intimamente conectados, embora seja tradição e idioma usar a notação de matriz em expressões para referenciar o armazenamento em objetos declarados e / ou definidos como matrizes. Você pode facilmente usar a notação de matriz com um tipo de ponteiro para tornar a aritmética do ponteiro mais limpa e mais significativa. De fato, em C, uma expressão da forma
e1[e2]
é precisamente equivalente à expressão*((e1)+(e2))
. A conversão binária usual é aplicada aos dois operandos e o resultado é sempre um valor l . Como o operador de indireção (*
) deve ter um ponteiro como operando, um dee1
ee2
deve ser um ponteiro e o outro deve ser um número inteiro, mas não importa qualuma vez que a conversão unária inicial para qualquer "matriz de T" é convertê-la em "ponteiro para T". A notação de matriz em expressões é uma macro do compilador (no nível da linguagem) para gerar expressões aritméticas de ponteiro.Então, realmente C já funciona da maneira que você sugere, mas você está confundindo o uso da notação em dois contextos muito separados.
fonte