Eu estava lendo um código e descobri que a pessoa estava usando arr[-2]
para acessar o 2º elemento antes do arr
, assim:
|a|b|c|d|e|f|g|
^------------ arr[0]
^---------- arr[1]
^---------------- arr[-2]
Isso é permitido?
Eu sei que arr[x]
é o mesmo que *(arr + x)
. Então arr[-2]
é *(arr - 2)
, o que parece OK. O que você acha?
somearray-2
é indefinida, a menos que o resultado esteja na faixa do iníciosomearray
a 1 após o fim.[]
eram referenciados como um açúcar de sintaxe para aritmética de ponteiros. A maneira favorita de confundir iniciantes é escrever1[arr]
- em vez dearr[1]
- e observá-los adivinhando o que isso significa.((E1)+(E2))
será um ponteiro (64 bits) com o valor esperado.Isso só é válido se
arr
for um ponteiro que aponta para o segundo elemento em uma matriz ou um elemento posterior. Caso contrário, não é válido, porque você acessaria a memória fora dos limites do array. Então, por exemplo, isso seria errado:Mas isso seria bom:
No entanto, é incomum usar um subscrito negativo.
fonte
int arr[10];
parte de uma estrutura com outros elementos antes dela,arr[-2]
poderia ser potencialmente bem definida e você poderia determinar se ela é baseada emoffsetof
etc.If one is sure that the elements exist, it is also possible to index backwards in an array; p[-1], p[-2], and so on are syntactically legal, and refer to the elements that immediately precede p[0]. Of course, it is illegal to refer to objects that are not within the array bounds.
Mesmo assim, seu exemplo é melhor para me ajudar a entendê-lo. Obrigado!Parece bom para mim. No entanto, seria raro você precisar dele legitimamente.
fonte
O que provavelmente era isso
arr
era apontar para o meio da matriz, portanto,arr[-2]
apontar para algo na matriz original sem sair dos limites.fonte
Não tenho certeza de quão confiável isso é, mas acabei de ler a seguinte advertência sobre índices de matriz negativos em sistemas de 64 bits (LP64, presumivelmente): http://www.devx.com/tips/Tip/41349
O autor parece estar dizendo que índices de array int de 32 bits com endereçamento de 64 bits podem resultar em cálculos de endereço incorretos, a menos que o índice de array seja explicitamente promovido para 64 bits (por exemplo, por meio de uma conversão ptrdiff_t). Na verdade, vi um bug de sua natureza com a versão PowerPC do gcc 4.1.0, mas não sei se é um bug do compilador (ou seja, deve funcionar de acordo com o padrão C99) ou comportamento correto (ou seja, o índice precisa ser convertido para 64 bits para o comportamento correto)?
fonte
Sei que a pergunta foi respondida, mas não resisti em compartilhar essa explicação.
Lembro-me dos Princípios de design do compilador. Vamos supor que a seja uma matriz int e o tamanho de int seja 2 e o endereço base de a seja 1000.
Como
a[5]
vai funcionar ->Essa explicação também é a razão pela qual índices negativos em matrizes funcionam em C.
ou seja, se eu acessar,
a[-5]
ele me daráEle me retornará o objeto no local 990. Por essa lógica, podemos acessar índices negativos no Array em C.
fonte
Sobre por que alguém iria querer usar índices negativos, usei-os em dois contextos:
Ter uma tabela de números combinatórios que informa comb [1] [- 1] = 0; você sempre pode verificar os índices antes de acessar a tabela, mas desta forma o código parece mais limpo e executa mais rápido.
Colocando um centinel no início de uma mesa. Por exemplo, você deseja usar algo como
mas então você também deve verificar se
i
é positivo.Solução: faça com que
a[-1]
seja-DBLE_MAX
, para quex<a[-1]
sempre seja falso.fonte
fonte