c arrays pointers unary-operator postfix-operator

c - ¿Qué es ''-1



arrays pointers (5)

Esta pregunta ya tiene una respuesta aquí:

Hoy me topé con un acertijo C que me sorprendió.

No pensé que -1 [p] en el siguiente ejemplo se compilaría, pero lo hizo. De hecho, x termina siendo -3.

int x; int array[] = {1, 2, 3}; int *p = &array[1]; x = -1[p]

Busqué en Internet algo como -1 [puntero] pero no pude encontrar nada. Está bien, es difícil ingresar la consulta de búsqueda correcta, lo admito. ¿Quién sabe por qué -1 [p] compila y X se convierte en -3?


De acuerdo con el Estándar C (6.5.2 operadores Postfix), el operador de subíndice se define de la siguiente manera

postfix-expression [ expression ]

Entonces, antes de los corchetes habrá una expresión postfix.

En esta declaración de expresión

x = -1[p];

se utiliza la expresión de postfix 1 (que es al mismo tiempo una expresión primaria), la expresión de postfix 1[p] (que es el operador de subíndice) y el operador unario - Tenga en cuenta que cuando el compilador divide un programa en tokens entonces las constantes enteras se consideran fichas sin el signo menos. menos es una ficha separada.

Entonces la declaración puede reescribirse como

x = -( 1[p] );

porque una expresión postfix tiene una prioridad más alta que una expresión unaria.

Consideremos al principio la subexpresión postfix 1[p]

De acuerdo con el Estándar C (6.5.2.1 Subscripting de matriz)

2 Una expresión de postfix seguida de una expresión entre corchetes [] es una designación con subíndice de un elemento de un objeto de matriz. La definición del operador de subíndice [] es que E1 [E2] es idéntico a (* ((E1) + (E2))). Debido a las reglas de conversión que se aplican al operador binario +, si E1 es un objeto de matriz (equivalente, un puntero al elemento inicial de un objeto de matriz) y E2 es un número entero, E1 [E2] designa el elemento E2-ésimo de E1 (contando desde cero).

Entonces esta sub-expresión se evalúa como *( ( 1 ) + ( p ) ) y es igual a *( ( p ) + ( 1 ) ).

Así, la declaración anterior

x = -1[p];

es equivalente a

x = -p[1];

y producirá -3 , porque el puntero p apunta al segundo elemento de la matriz debido a la declaración

int *p = &array[1];

y luego la expresión p[1] produce el valor del elemento después del segundo elemento de la matriz. Luego se aplica el operador unario.


Esta

int array[] = {1, 2, 3};

parece

array[0] array[1] array[2] -------------------------- | 1 | 2 | 3 | -------------------------- 0x100 0x104 0x108 <-- lets assume 0x100 is base address of array array

Siguiente cuando te gusta

int *p = &array[1];

el puntero entero p apunta a la dirección de la array[1] es decir, 0x104 . Parece que

array[0] array[1] array[2] -------------------------- | 1 | 2 | 3 | -------------------------- 0x100 0x104 0x108 <-- lets assume 0x100 is base address of array | p holds 0x104

Y cuando te gusta

x = -1[p]

-1[p] es equivalente a -(1[p]) es decir -(p[1]) . parece que

-(p[1]) ==> -(*(p + 1*4)) /* p holds points to array[1] i.e 0x104 */ ==> -(*(0x104 + 4)) ==> -(*(0x108)) ==> value at 0x108 is 3 ==> prints -3


Lo primero que debes descubrir es la precedencia. A saber, [] tiene mayor prioridad que los operadores unarios, por lo que -1[p] es igual a -(1[p]) , no (-1)[p] . Entonces tomamos el resultado de 1[p] y lo negamos.

x[y] es igual a *(x+y) , entonces 1[p] es igual a *(1+p) , que es igual a *(p+1) , que es igual a p[1] .

Entonces, tomamos el elemento uno después de donde p apunta, entonces el tercer elemento de la array , es decir, 3, y luego lo negamos, lo que nos da -3 .


Lo que sucede aquí es realmente interesante.

p [n] significa *(p+n) . Es por eso que ve 3, porque "p" apunta a la matriz [1] que es 2, y -p [1] se interpreta como -(*(p+1)) que es -3.


Soy la persona que hizo este "acertijo" (ver mi publicación de Twitter )

¡Entonces! ¿Qué pasa con -1 [p]?

ISO C en realidad define [] como simétrico, lo que significa que x[y] es lo mismo que y[x] , donde x e y son ambas expresiones.

Ingenuamente, podríamos llegar a la conclusión de que -1[p] es, por lo tanto, p[-1] y, por lo tanto, x = 1 Sin embargo, -1 es en realidad el operador menos unario aplicado a la constante 1, y el menos unario tiene una precedencia más baja que []

Entonces, -1[p] es -(p[1]) , que produce -3.

Esto también puede conducir a fragmentos de aspecto funky como este:

sizeof(char)["abc"] /* yields ''b'' */