Por que a indexação em uma matriz começa com zero em C e não com 1?
Por que a indexação em uma matriz começa com zero em C e não com 1?
Respostas:
Em C, o nome de uma matriz é essencialmente um ponteiro [mas veja os comentários] , uma referência a um local de memória e, portanto, a expressão array[n]
se refere a n
elementos de um local de memória distantes do elemento inicial. Isso significa que o índice é usado como um deslocamento. O primeiro elemento da matriz está exatamente contido no local da memória a que a matriz se refere (a 0 elemento de distância), portanto, deve ser indicado como array[0]
.
Para mais informações:
http://developeronline.blogspot.com/2008/04/why-array-index-should-start-from-0.html
sizeof arr
gera o tamanho do objeto da matriz, não o tamanho de um ponteiro.
sizeof
operador, ou o &
operador unário , ou é uma cadeia de caracteres literal usada para inicializar uma matriz, uma expressão com o tipo" matriz do tipo "é convertido para uma expressão com o tipo" ponteiro para o tipo "que aponta para o elemento inicial do objeto da matriz e não é um lvalue. Se o objeto da matriz tiver classe de armazenamento de registro, o comportamento será indefinido. "
Esta pergunta foi publicada há mais de um ano, mas aqui vai ...
Embora o artigo de Dijkstra (anteriormente mencionado em uma resposta agora excluída ) faça sentido de uma perspectiva matemática, ele não é tão relevante quando se trata de programação.
A decisão tomada pela especificação de linguagem e pelos projetistas de compiladores é baseada na decisão dos projetistas de sistemas de computador de iniciar a contagem em 0.
Citação de um pedido de paz de Danny Cohen.
Para qualquer base b, os primeiros números inteiros não negativos b ^ N são representados por exatamente N dígitos (incluindo zeros à esquerda) apenas se a numeração começar em 0.
Isso pode ser testado facilmente. Na base 2, pegue 2^3 = 8
o 8º número é:
111
pode ser representado usando 3
bits, enquanto 1000
exigirá um bit extra (4 bits).
Os endereços de memória do computador têm 2^N
células endereçadas por N
bits. Agora, se começarmos a contar com 1, as 2^N
células precisarão de N+1
linhas de endereço. O bit extra é necessário para acessar exatamente 1 endereço. ( 1000
no caso acima.). Outra maneira de resolver isso seria deixar o último endereço inacessível e usar N
linhas de endereço.
Ambas são soluções subótimas , em comparação com a contagem inicial em 0, que manteria todos os endereços acessíveis, usando exatamente N
as linhas de endereço!
A decisão de começar a contar em 0
, desde então, permeou todos os sistemas digitais , incluindo o software executado neles, porque facilita a conversão do código para o que o sistema subjacente pode interpretar. Se não fosse assim, haveria uma operação de conversão desnecessária entre a máquina e o programador, para cada acesso ao array. Facilita a compilação.
Citando o artigo:
a[b]
foi implementado como *(a+b)
nos primeiros compiladores. Ainda hoje você ainda pode escrever em 2[a]
vez de a[2]
. Agora, se os índices não começassem em 0, eles a[b]
se tornariam *(a+b-1)
. Isso exigiria 2 adições nas CPUs do tempo em vez de 0, o que significa metade da velocidade. Claramente não é desejável.
Porque 0 é o quão longe o ponteiro está da cabeça da matriz e o primeiro elemento da matriz.
Considerar:
int foo[5] = {1,2,3,4,5};
Para acessar 0, fazemos:
foo[0]
Mas foo se decompõe em um ponteiro, e o acesso acima tem uma maneira aritmética de ponteiro análogo de acessá-lo
*(foo + 0)
Atualmente, a aritmética dos ponteiros não é usada com tanta frequência. Quando, porém, era uma maneira conveniente de pegar um endereço e afastar X "ints" desse ponto de partida. Claro que se você quiser ficar onde está, basta adicionar 0!
Como o índice baseado em 0 permite ...
array[index]
... para ser implementado como ...
*(array + index)
Se o índice fosse baseado em 1, o compilador precisaria gerar:, *(array + index - 1)
e esse "-1" prejudicaria o desempenho.
Porque tornou o compilador e o vinculador mais simples (mais fáceis de escrever).
"... Fazer referência à memória por um endereço e um deslocamento é representado diretamente no hardware em praticamente todas as arquiteturas de computadores; portanto, esse detalhe de design em C facilita a compilação"
e
"... isso facilita a implementação ..."
O índice da matriz sempre começa com zero. Vamos supor que o endereço base seja 2000. Agora arr[i] = *(arr+i)
. Agora if i= 0
, isso significa que *(2000+0
) é igual ao endereço base ou endereço do primeiro elemento na matriz. esse índice é tratado como deslocamento, portanto, o índice de bydeafault começa do zero.
Pela mesma razão que, quando é quarta-feira e alguém pergunta quantos dias até quarta-feira, você diz 0 em vez de 1 e que quando é quarta-feira e alguém pergunta quantos dias até quinta-feira, você diz 1 em vez de 2.
A explicação mais elegante que li para numeração com base em zero é uma observação de que os valores não são armazenados nos locais marcados na linha numérica, mas nos espaços entre eles. O primeiro item é armazenado entre zero e um, o próximo entre um e dois, etc. O enésimo item é armazenado entre N-1 e N. Um intervalo de itens pode ser descrito usando os números de ambos os lados. Os itens individuais são descritos por convenção, usando os números abaixo. Se alguém recebe um intervalo (X, Y), identificar números individuais usando o número abaixo significa que é possível identificar o primeiro item sem usar aritmética (é o item X), mas é preciso subtrair um de Y para identificar o último item (Y -1). A identificação de itens usando o número acima facilitaria a identificação do último item em um intervalo (seria o item Y),
Embora não seja horrível identificar itens com base no número acima deles, definir o primeiro item no intervalo (X, Y) como sendo o item acima X geralmente funciona mais bem do que defini-lo como o item abaixo (X + 1)
A razão técnica pode derivar do fato de que o ponteiro para um local de memória de uma matriz é o conteúdo do primeiro elemento da matriz. Se você declarar o ponteiro com um índice de um, os programas normalmente adicionariam esse valor de um ao ponteiro para acessar o conteúdo que não é o que você deseja, é claro.
Tente acessar uma tela de pixel usando as coordenadas X, Y em uma matriz baseada em 1. A fórmula é totalmente complexa. Por que é complexo? Como você acaba convertendo as cordas X, Y em um número, o deslocamento. Por que você precisa converter X, Y em um deslocamento? Porque é assim que a memória é organizada dentro dos computadores, como um fluxo contínuo de células de memória (matrizes). Como os computadores lidam com as células da matriz? Usando deslocamentos (deslocamentos da primeira célula, um modelo de indexação baseado em zero).
Portanto, em algum momento do código, você precisa (ou o compilador precisa) converter a fórmula de 1 base em uma fórmula de 0 porque é assim que os computadores lidam com a memória.
Suponha que desejemos criar uma matriz de tamanho 5
int array [5] = [2,3,5,9,8]
deixe o primeiro elemento da matriz apontar para o local 100
e consideremos que a indexação começa em 1 e não em 0.
agora temos que encontrar a localização do 1º elemento com a ajuda do índice
(lembre-se de que a localização do 1º elemento é 100),
pois o tamanho de um número inteiro é de 4 bits,
portanto -> considerando o índice 1, a posição seria do
tamanho do índice (1) * tamanho do número inteiro (4) = 4,
então a posição real que ele nos mostrará é
100 + 4 = 104
o que não é verdade porque o local inicial era 100.
ele deveria estar apontando para 100 e não para 104
isso está errado
agora, suponha que tenhamos retirado a indexação de 0,
então a
posição do 1º elemento deve ser o
tamanho do índice (0) * tamanho do número inteiro (4) = 0,
portanto -> a
localização do 1º elemento é 100 + 0 = 100
e essa foi a localização real do elemento;
é por isso que a indexação começa em 0;
Espero que isso esclareça seu ponto de vista.
Eu sou de um fundo Java. Apresentei resposta a esta pergunta no diagrama abaixo, que escrevi em um pedaço de papel que é auto-explicativo
Etapas principais:
Nota : Os blocos mostrados na imagem são representados na memória
Antes de tudo, você precisa saber que matrizes são consideradas internamente como ponteiros porque o "nome da matriz em si contém o endereço do primeiro elemento da matriz"
ex. int arr[2] = {5,4};
considere que a matriz começa no endereço 100, portanto, o primeiro elemento do elemento estará no endereço 100 e o segundo estará em 104 agora, considere que, se o índice da matriz começar em 1, então
arr[1]:-
isso pode ser escrito na expressão ponteiros como esta-
arr[1] = *(arr + 1 * (size of single element of array));
considere o tamanho de int é 4 bytes, agora,
arr[1] = *(arr + 1 * (4) );
arr[1] = *(arr + 4);
como sabemos o nome da matriz contém o endereço do seu primeiro elemento, então arr = 100 agora,
arr[1] = *(100 + 4);
arr[1] = *(104);
que dá,
arr[1] = 4;
por causa dessa expressão, não podemos acessar o elemento no endereço 100, que é o primeiro elemento oficial,
Agora considere o índice da matriz começa em 0, então
arr[0]:-
isso será resolvido como
arr[0] = *(arr + 0 + (size of type of array));
arr[0] = *(arr + 0 * 4);
arr[0] = *(arr + 0);
arr[0] = *(arr);
agora, sabemos que o nome da matriz contém o endereço do seu primeiro elemento,
arr[0] = *(100);
o que dá o resultado correto
arr[0] = 5;
portanto, o índice de matriz sempre começa de 0 em c.
referência: todos os detalhes estão escritos no livro "A linguagem de programação C de brian kerninghan e dennis ritchie"
Na matriz, o índice indica a distância do elemento inicial. Portanto, o primeiro elemento está a 0 distância do elemento inicial. Então, é por isso que a matriz começa em 0.
Isso ocorre porque ele address
tem que apontar para a direita element
na matriz. Vamos assumir a matriz abaixo:
let arr = [10, 20, 40, 60];
Vamos agora considerar o início do endereço 12
e o tamanho do element
ser 4 bytes
.
address of arr[0] = 12 + (0 * 4) => 12
address of arr[1] = 12 + (1 * 4) => 16
address of arr[2] = 12 + (2 * 4) => 20
address of arr[3] = 12 + (3 * 4) => 24
Se fosse não zero-based
, tecnicamente nosso primeiro endereço elemento na array
seria 16
o que é errado, pois de localização é 12
.
O nome da matriz é um ponteiro constante que aponta para o endereço base. Quando você usa arr [i] o compilador a manipula como * (arr + i). Como o intervalo int é -128 a 127, o compilador pensa que -128 a -1 são números negativos e 0 a 128 são números positivos. Portanto, o índice da matriz sempre começa com zero.
int
necessário um tipo para oferecer suporte a pelo menos um intervalo de 16 bits e, na maioria dos sistemas hoje em dia, suporta 32 bits. Eu acho que sua lógica é falha e sua resposta realmente não melhora nas outras respostas já fornecidas por outras pessoas. Sugiro excluir isso.