Pregunta Con las matrices, ¿por qué es que a [5] == 5 [a]?


Como Joel señala en Stack Overflow podcast # 34, en C Lenguaje de programación (alias: K & R), se menciona esta propiedad de las matrices en C: a[5] == 5[a]

Joel dice que es debido a la aritmética del puntero, pero todavía no entiendo. Por que a[5] == 5[a]?


1427
2017-12-19 17:01


origen


Respuestas:


El estándar C define el [] operador de la siguiente manera:

a[b] == *(a + b)

Por lo tanto a[5] evaluará a:

*(a + 5)

y 5[a] evaluará a:

*(5 + a)

a es un puntero al primer elemento de la matriz. a[5] es el valor que es 5 elementos lejos de a, que es lo mismo que *(a + 5), y de las matemáticas de la escuela primaria sabemos que son iguales (se agrega conmutativo)


1704
2017-12-19 17:04



Porque el acceso a la matriz se define en términos de punteros. a[i] se define para significar *(a + i), que es conmutativo.


273
2017-12-19 17:05



Creo que algo está pasando por alto por las otras respuestas.

Sí, p[i] es por definición equivalente a *(p+i), que (porque la suma es conmutativa) es equivalente a *(i+p), que (de nuevo, según la definición de [] operador) es equivalente a i[p].

(Y en array[i], el nombre de la matriz se convierte implícitamente en un puntero al primer elemento de la matriz).

Pero la conmutatividad de la suma no es tan obvia en este caso.

Cuando ambos operandos son del mismo tipo, o incluso de diferentes tipos numéricos que se promueven a un tipo común, la conmutatividad tiene mucho sentido: x + y == y + x.

Pero en este caso estamos hablando específicamente de la aritmética del puntero, donde un operando es un puntero y el otro es un número entero. (Entero + entero es una operación diferente, y el puntero + puntero no tiene sentido).

La descripción del estándar C de + operador (N1570 6.5.6) dice:

Además, ambos operandos deben tener tipo aritmético o uno   operando debe ser un puntero a un tipo de objeto completo y el otro   tendrá un tipo entero.

Podría haber dicho tan fácilmente:

Además, ambos operandos tendrán un tipo aritmético, o la izquierda   operando debe ser un puntero a un tipo de objeto completo y el operando derecho   tendrá un tipo entero.

en cuyo caso ambos i + p y i[p] sería ilegal

En términos de C ++, realmente tenemos dos conjuntos de sobrecarga + operadores, que se pueden describir libremente como:

pointer operator+(pointer p, integer i);

y

pointer operator+(integer i, pointer p);

de los cuales solo el primero es realmente necesario.

Entonces, ¿por qué es así?

C ++ heredó esta definición de C, que la obtuvo de B (la conmutatividad de la indexación de matrices se menciona explícitamente en 1972). Referencia de los usuarios a B), que lo consiguió BCPL (manual de 1967), que bien pudo haberlo obtenido incluso de idiomas anteriores (CPL? Algol?).

Entonces, la idea de que la indexación de matrices se define en términos de suma, y ​​que la suma, incluso de un puntero y un entero, es conmutativa, se remonta a muchas décadas, a los lenguajes ancestrales de C.

Esos idiomas se escribieron mucho menos fuertemente que el C moderno. En particular, la distinción entre punteros y enteros a menudo se ignoraba. (Los programadores de Early C a veces usaban punteros como enteros sin signo, antes del unsigned se agregó la palabra clave al idioma.) De modo que la idea de hacer una adición no conmutativa porque los operandos son de diferentes tipos probablemente no se les habría ocurrido a los diseñadores de esos idiomas. Si un usuario desea agregar dos "cosas", ya sea que esas "cosas" sean enteros, punteros u otra cosa, no le correspondía al lenguaje evitarlo.

Y a lo largo de los años, cualquier cambio en esa regla habría roto el código existente (aunque el estándar ANSI C de 1989 podría haber sido una buena oportunidad).

Cambiar C y / o C ++ para requerir poner el puntero a la izquierda y el entero a la derecha podría romper un código existente, pero no habría pérdida de poder expresivo real.

Entonces ahora tenemos arr[3] y 3[arr] significa exactamente lo mismo, aunque la última forma nunca debe aparecer fuera del IOCCC.


186
2017-08-23 01:37



Y por supuesto

 ("ABCD"[2] == 2["ABCD"]) && (2["ABCD"] == 'C') && ("ABCD"[2] == 'C')

La razón principal de esto fue que en los años 70, cuando se diseñó C, las computadoras no tenían mucha memoria (64 KB era mucho), por lo que el compilador de C no hizo mucha comprobación de sintaxis. Por lo tanto "X[Y]"fue traducido ciegamente a"*(X+Y)"

Esto también explica el "+="y"++"sintaxis. Todo en la forma"A = B + C"tenía la misma forma compilada. Pero si B era el mismo objeto que A, entonces estaba disponible una optimización de nivel de ensamblado. Pero el compilador no era lo suficientemente brillante como para reconocerlo, por lo que el desarrollador tenía que (A += C) Del mismo modo, si C estaba 1, una optimización de nivel de ensamblado diferente estaba disponible, y nuevamente el desarrollador tuvo que hacerlo explícito, porque el compilador no lo reconoció. (Más recientemente los compiladores lo hacen, por lo que esas sintaxis son en gran medida innecesarias en estos días)


184
2017-12-19 17:07



Una cosa que nadie parece haber mencionado sobre el problema de Dinah con sizeof:

Solo puede agregar un entero a un puntero, no puede agregar dos punteros juntos. De esta forma, al agregar un puntero a un entero o un entero a un puntero, el compilador siempre sabe qué bit tiene un tamaño que debe tenerse en cuenta.


51
2018-02-11 15:56



Para responder la pregunta literalmente. No siempre es cierto que x == x

double zero = 0.0;
double a[] = { 0,0,0,0,0, zero/zero}; // NaN
cout << (a[5] == 5[a] ? "true" : "false") << endl;

huellas dactilares

false

46
2017-08-11 13:50



Buena pregunta / respuestas.

Solo quiero señalar que los punteros C y las matrices no son mismo, aunque en este caso la diferencia no es esencial.

Considere las siguientes declaraciones:

int a[10];
int* p = a;

En a.out, el símbolo un está en una dirección que es el comienzo de la matriz y el símbolo pag está en una dirección donde se almacena un puntero, y el valor del puntero en esa ubicación de memoria es el comienzo de la matriz.


23
2017-12-20 08:16