Estaba leyendo un código y descubrí que la persona estaba usando arr[-2]
para acceder al segundo elemento antes del arr
, así:
|a|b|c|d|e|f|g|
^------------ arr[0]
^---------- arr[1]
^---------------- arr[-2]
eso está permitido?
Sé que arr[x]
es lo mismo que *(arr + x)
. También lo arr[-2]
es *(arr - 2)
, lo que parece estar bien. ¿Qué piensas?
somearray-2
no está definida a menos que el resultado esté en el rango desde el inicio desomearray
hasta 1 después de su final.[]
se hacía referencia a ellos como un azúcar sintáctico para la aritmética de punteros. La forma favorita de confundir a los principiantes es escribir1[arr]
, en lugar dearr[1]
, y verlos adivinar lo que se supone que significa.((E1)+(E2))
será un puntero (de 64 bits) con el valor esperado.Esto solo es válido si
arr
es un puntero que apunta al segundo elemento de una matriz o un elemento posterior. De lo contrario, no es válido, porque accedería a la memoria fuera de los límites de la matriz. Entonces, por ejemplo, esto estaría mal:Pero esto estaría bien:
Sin embargo, es inusual utilizar un subíndice negativo.
fuente
int arr[10];
eran parte de una estructura con otros elementos antes de ella,arr[-2]
podría potencialmente ser bien definidos, y se podía determinar si se basa enoffsetof
, etcIf 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.
Aún así, su ejemplo es mejor para ayudarme a entenderlo. ¡Gracias!Me suena bien. Sin embargo, sería un caso raro que lo necesitara legítimamente.
fuente
Lo que probablemente era eso
arr
apuntaba al medio de la matriz, por lo tanto,arr[-2]
apuntaba a algo en la matriz original sin salirse de los límites.fuente
No estoy seguro de cuán confiable es esto, pero acabo de leer la siguiente advertencia sobre los índices de matriz negativos en sistemas de 64 bits (presumiblemente LP64): http://www.devx.com/tips/Tip/41349
El autor parece estar diciendo que los índices de matriz int de 32 bits con direccionamiento de 64 bits pueden resultar en cálculos de direcciones incorrectos a menos que el índice de matriz se promueva explícitamente a 64 bits (por ejemplo, a través de una conversión ptrdiff_t). De hecho, he visto un error de su naturaleza con la versión PowerPC de gcc 4.1.0, pero no sé si es un error del compilador (es decir, debería funcionar de acuerdo con el estándar C99) o un comportamiento correcto (es decir, el índice necesita una conversión a 64 bits para un comportamiento correcto)?
fuente
Sé que la pregunta está respondida, pero no pude resistirme a compartir esta explicación.
Recuerdo los principios del diseño del compilador, supongamos que a es una matriz int y el tamaño de int es 2, y la dirección base de a es 1000.
Cómo
a[5]
funcionará ->Esta explicación también es la razón por la que los índices negativos en matrices funcionan en C.
es decir, si
a[-5]
accedo me daráMe devolverá el objeto en la ubicación 990. Mediante esta lógica, podemos acceder a índices negativos en Array en C.
fuente
Acerca de por qué alguien querría usar índices negativos, los he usado en dos contextos:
Tener una tabla de números combinatorios que te diga comb [1] [- 1] = 0; siempre puede verificar los índices antes de acceder a la tabla, pero de esta manera el código se ve más limpio y se ejecuta más rápido.
Poner un centinela al principio de una mesa. Por ejemplo, quieres usar algo como
pero también debes comprobar que
i
sea positivo.Solución: haz que
a[-1]
sea-DBLE_MAX
así, para quex<a[-1]
siempre sea falso.fuente
fuente