Con matrices, ¿por qué ocurre que a [5] == 5 [a]?

Como señala Joel en Podcast de Stack Overflow n. ° 34en Lenguaje de programación C (también conocido como: K & R), se menciona esta propiedad de las matrices en C: a[5] == 5[a]

Joel dice que se debe a la aritmética de punteros, pero todavía no lo entiendo. Por que a[5] == 5[a]?

preguntado el 19 de diciembre de 08 a las 15:12

¿Algo como un [+] también funcionaría como * (a ++) O * (++ a)? -

@Egon: Eso es muy creativo, pero desafortunadamente no es así como funcionan los compiladores. El compilador interpreta a[1] como una serie de tokens, no cadenas: * ({ubicación entera de} a {operador} + {entero} 1) es lo mismo que * ({entero} 1 {operador} + {ubicación entera de} a) pero no es lo mismo que * ({ubicación entera de} un {operador} + {operador} +) -

Una variación compuesta interesante sobre esto se ilustra en Acceso ilógico a la matriz, donde tienes char bar[]; int foo[]; y foo[i][bar] se utiliza como expresión. -

@EldritchConundrum, ¿por qué cree que 'el compilador no puede verificar que la parte izquierda sea un puntero'? Sí puede. Eso es verdad a[b] = *(a + b) para cualquier a y b, pero fue la elección libre de los diseñadores de idiomas para + por definir conmutativa para todos los tipos. Nada podría impedirles prohibir i + p mientras permite p + i. -

@Andrey One suele esperar + para ser conmutativo, por lo que tal vez el problema real sea elegir hacer que las operaciones de puntero se parezcan a la aritmética, en lugar de diseñar un operador de desplazamiento separado. -

17 Respuestas

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

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

Por lo tanto a[5] evaluará para:

*(a + 5)

y 5[a] evaluará para:

*(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 (la suma es conmutativo).

respondido 30 nov., 16:10

Me pregunto si no es más como * ((5 * sizeof (a)) + a). Sin embargo, gran explicación. - John Mac Intyre

@Dinah: Desde la perspectiva del compilador C, tienes razón. No se necesita sizeof y esas expresiones que mencioné son LAS MISMAS. Sin embargo, el compilador tendrá en cuenta sizeof al producir código de máquina. Si a es una matriz int, a[5] se compilará en algo como mov eax, [ebx+20] en lugar de [ebx+5] - mmx

@Dinah: A es una dirección, digamos 0x1230. Si a estaba en una matriz int de 32 bits, entonces a [0] está en 0x1230, a [1] está en 0x1234, a [2] en 0x1238 ... a [5] en x1244 etc. 5x0, obtenemos 1230x0, que es incorrecto. - James Curran

@ sr105: Ese es un caso especial para el operador +, donde uno de los operandos es un puntero y el otro un entero. El estándar dice que el resultado será del tipo de puntero. El compilador / tiene que ser / suficientemente inteligente. - aib

"De las matemáticas de la escuela primaria sabemos que son iguales" - Entiendo que estás simplificando, pero estoy con aquellos que sienten que esto es encimasimplificando. No es elemental que *(10 + (int *)13) != *((int *)10 + 13). En otras palabras, aquí hay más cosas que aritmética de la escuela primaria. La conmutatividad se basa fundamentalmente en que el compilador reconozca qué operando es un puntero (y qué tamaño de objeto). Para decirlo de otra manera, (1 apple + 2 oranges) = (2 oranges + 1 apple), pero (1 apple + 2 oranges) != (1 orange + 2 apples). - LarsH

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

contestado el 13 de mayo de 11 a las 14:05

Las matrices no se definen en términos de punteros, pero el acceso para ellos es. - Carreras de ligereza en órbita

Yo agregaría "por lo que es igual a *(i + a), que se puede escribir como i[a]". - jim balter

Le sugiero que incluya la cita del estándar, que es la siguiente: 6.5.2.1: 2 Una expresión de sufijo seguida de una expresión entre corchetes [] es una designación subindicada 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 (de manera 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). - valor

Para ser más correctos: las matrices se descomponen en punteros cuando accede a ellas. - 12431234123412341234123

Nitpick: No tiene sentido decir eso "*(a + i) es conmutativa ". Sin embargo, *(a + i) = *(i + a) = i[a] porque adición es conmutativo. - andreas rejbrand

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

Sí, p[i] es por definición equivalente a *(p+i), que (debido a que la suma es conmutativa) es equivalente a *(i+p), que (de nuevo, según la definición del [] 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 perfecto sentido: x + y == y + x.

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

La descripción de la norma C de la + operadorN1570 6.5.6) dice:

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

Con la misma facilidad podría haber dicho:

Para la suma, ambos operandos deben tener 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 sobrecargas + operadores, que se pueden describir vagamente como:

pointer operator+(pointer p, integer i);

y

pointer operator+(integer i, pointer p);

de los cuales sólo 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 obtuvo de BCPL (manual fechado en 1967), que bien puede haberlo obtenido incluso de lenguajes 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 atrás, a los lenguajes ancestros de C.

Esos lenguajes se escribieron con mucha menos fuerza que el C moderno. En particular, a menudo se ignoraba la distinción entre punteros y números enteros. (Los primeros programadores de C a veces usaban punteros como enteros sin signo, antes de unsigned la palabra clave se agregó al lenguaje). Entonces, la idea de hacer que la adición no sea conmutativa porque los operandos son de diferentes tipos probablemente no se les hubiera ocurrido a los diseñadores de esos lenguajes. Si un usuario quisiera agregar dos "cosas", ya sean esas "cosas" números enteros, punteros o cualquier otra cosa, no estaba en manos del idioma evitarlo.

Y a lo largo de los años, cualquier cambio a 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 que requiera colocar el puntero a la izquierda y el entero a la derecha podría romper algún 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 COICC.

Respondido el 28 de enero de 16 a las 20:01

Fantástica descripción de esta propiedad. Desde un punto de vista de alto nivel, creo 3[arr] es un artefacto interesante, pero rara vez debería usarse. La respuesta aceptada a esta pregunta (stackoverflow.com/q/1390365/356>) que pregunté hace un tiempo ha cambiado mi forma de pensar sobre la sintaxis. Aunque a menudo técnicamente no existe una forma correcta o incorrecta de hacer estas cosas, este tipo de características lo hacen pensar de una manera que está separada de los detalles de implementación. Hay beneficios en esta forma diferente de pensar que en parte se pierde cuando se fija en los detalles de implementación. - Dina

La suma es conmutativa. Que el estándar C lo defina de otra manera sería extraño. Es por eso que no podría decir con la misma facilidad: "Para la suma, ambos operandos deben tener un tipo aritmético, o el operando izquierdo debe ser un puntero a un tipo de objeto completo y el operando derecho debe tener un tipo entero". - Eso no tendría sentido para la mayoría de las personas que agregan cosas. - iheanyi

@iheanyi: la suma suele ser conmutativa, y normalmente toma dos operandos del mismo tipo. La suma de punteros le permite agregar un puntero y un número entero, pero no dos punteros. En mi humilde opinión, ese ya es un caso especial suficientemente extraño que requerir que el puntero sea el operando izquierdo no sería una carga significativa. (Algunos lenguajes usan "+" para la concatenación de cadenas; eso ciertamente no es conmutativo.) - Keith Thompson

@supercat, eso es aún peor. Eso significaría que a veces x + 1! = 1 + x. Eso violaría por completo la propiedad asociativa de la suma. - iheanyi

@iheanyi: Creo que te refieres a la propiedad conmutativa; la adición ya no es asociativa, ya que en la mayoría de las implementaciones (1LL + 1U) -2! = 1LL + (1U-2). De hecho, el cambio haría asociativas algunas situaciones que actualmente no lo son, por ejemplo, 3U + (UINT_MAX-2L) sería igual a (3U + UINT_MAX) -2. Sin embargo, lo mejor es que el lenguaje agregue nuevos tipos distintos para enteros promocionables y anillos algebraicos "envolventes", de modo que sumar 2 a un ring16_t que contiene 65535 produciría un ring16_t con valor 1, independiente del tamaño de int. - Super gato

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 (64KB era mucha), por lo que el compilador de C no revisó mucho la sintaxis. Por eso "X[Y]"fue traducido a ciegas"*(X+Y)"

Esto también explica el "+="Y"++"sintaxis. Todo en el formulario"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 ensamblaje. Pero el compilador no era lo suficientemente brillante para reconocerlo, por lo que el desarrollador tuvo que (A += C). Del mismo modo, si C fue 1, estaba disponible una optimización de nivel de ensamblaje diferente, y nuevamente el desarrollador tuvo que hacerlo explícito, porque el compilador no lo reconoció. (Los compiladores más recientes lo hacen, por lo que esas sintaxis son en gran medida innecesarias en estos días)

Respondido 28 Jul 17, 18:07

En realidad, eso se evalúa como falso; el primer término "ABCD" [2] == 2 ["ABCD"] se evalúa como verdadero, o 1, y 1! = 'C': D - jonathan leffler

@Jonathan: la misma ambigüedad llevó a la edición del título original de esta publicación. ¿Somos las marcas iguales equivalencia matemática, sintaxis de código o pseudocódigo? Yo sostengo la equivalencia matemática, pero como estamos hablando de código, no podemos escapar de que estamos viendo todo en términos de sintaxis de código. - Dina

¿No es esto un mito? Quiero decir que los operadores + = y ++ se crearon para simplificar para el compilador. Algún código se vuelve más claro con ellos, y es útil tener una sintaxis, sin importar lo que haga el compilador con él. - Thomas Padrón-McCarthy

+ = y ++ tiene otro beneficio significativo. si el lado izquierdo cambia alguna variable mientras se evalúa, el cambio solo se hará una vez. a = a + ...; lo haré dos veces. - Johannes Schaub - litb

No - "ABCD" [2] == * ("ABCD" + 2) = * ("CD") = 'C'. Desreferenciar una cadena le da un carácter, no una subcadena - MSalters

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

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

Respondido el 18 de diciembre de 09 a las 08:12

Hay una conversación bastante exhaustiva sobre esto en los comentarios de la respuesta aceptada. Hice referencia a dicha conversación en la edición a la pregunta original, pero no abordé directamente su muy válida preocupación de sizeof. No estoy seguro de cuál es la mejor manera de hacer esto en SO. ¿Debo hacer otra edición al original. ¿pregunta? - Dina

Me gustaría señalar que no puedes add punteros, pero puedes sustraer punteros (que devuelven el número de elementos entre). - U. Viento

Para responder a 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

Respondido 11 ago 11, 14:08

En realidad, un "nan" no es igual a sí mismo: cout << (a[5] == a[5] ? "true" : "false") << endl; is false. - Verdadero

@TrueY: Dijo eso específicamente para el caso de NaN (y específicamente que x == x no siempre es cierto). Creo que esa era su intención. Así que él es técnicamente correcto (y posiblemente, como dicen, el mejor tipo de corrección!). - Tim Cas

La pregunta es sobre C, su código no es código C. También hay una NAN in <math.h>, que es mejor que 0.0/0.0, porque 0.0/0.0 es UB cuando __STDC_IEC_559__ no está definido (la mayoría de las implementaciones no definen __STDC_IEC_559__, pero en la mayoría de las implementaciones 0.0/0.0 seguirá funcionando) - 12431234123412341234123

Acabo de descubrir que esta fea sintaxis podría ser "útil", o al menos muy divertida de jugar cuando quieres lidiar con una matriz de índices que se refieren a posiciones en la misma matriz. ¡Puede reemplazar los corchetes anidados y hacer que el código sea más legible!

int a[] = { 2 , 3 , 3 , 2 , 4 };
int s = sizeof a / sizeof *a;  //  s == 5

for(int i = 0 ; i < s ; ++i) {  
           
    cout << a[a[a[i]]] << endl;
    // ... is equivalent to ...
    cout << i[a][a][a] << endl;  // but I prefer this one, it's easier to increase the level of indirection (without loop)
    
}

Por supuesto, estoy bastante seguro de que no hay un caso de uso para eso en el código real, pero lo encontré interesante de todos modos :)

Respondido 31 ago 20, 04:08

Cuando veas i[a][a][a] crees que es un puntero a una matriz o una matriz de un puntero a una matriz o una matriz ... y a es un índice. Cuando veas a[a[a[i]]], cree que a es un puntero a una matriz o una matriz y i es un índice. - 12431234123412341234123

¡Guau! Es muy bueno el uso de esta función "estúpida". Podría ser útil en concurso algorítmico en algunos problemas)) - serge breúsov

Buena pregunta / respuestas.

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

Considere las siguientes declaraciones:

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

In a.out, el símbolo a está en una dirección que es el comienzo de la matriz, y el símbolo p 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.

Respondido el 01 de junio de 20 a las 05:06

No, técnicamente no son lo mismo. Si define algún b como int * const y lo hace apuntar a una matriz, sigue siendo un puntero, lo que significa que en la tabla de símbolos, b se refiere a una ubicación de memoria que almacena una dirección, que a su vez apunta a donde está la matriz . - polipensador

Muy buen punto. Recuerdo haber tenido un error muy desagradable cuando definí un símbolo global como char s [100] en un módulo, lo declaro como extern char * s; en otro módulo. Después de vincularlo todo, el programa se comportó de manera muy extraña. Porque el módulo que usa la declaración extern estaba usando los bytes iniciales de la matriz como un puntero a char. - Giorgio

Originalmente, en el abuelo BCPL de C, una matriz era un puntero. Es decir, lo que obtuviste cuando escribiste (lo he transcrito a C) int a[10] era un puntero llamado 'a', que apuntaba a una tienda suficiente para 10 enteros, en otro lugar. Por lo tanto, a + i y j + i tenían la misma forma: agregue el contenido de un par de ubicaciones de memoria. De hecho, creo que BCPL no tenía tipo, por lo que eran idénticos. Y la escala de tamaño de tipo no se aplicó, ya que BCPL estaba puramente orientado a palabras (también en máquinas con direcciones de palabras). - Dave

Creo que la mejor forma de entender la diferencia es comparar int*p = a; a int b = 5; En este último, "b" y "5" son números enteros, pero "b" es una variable, mientras que "5" es un valor fijo. De manera similar, "p" y "a" son direcciones de un carácter, pero "a" es un valor fijo. - James Curran

Si bien esta "respuesta" no responde a la pregunta (y por lo tanto debería ser un comentario, no una respuesta), podría resumir como "una matriz no es un valor l, pero un puntero sí lo es". - U. Viento

Para punteros en C, tenemos

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

y también

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

De ahí que sea cierto que a[5] == 5[a].

respondido 23 mar '12, 17:03

No es una respuesta, sino algo para pensar. Si la clase tiene un operador de índice / subíndice sobrecargado, la expresión 0[x] no trabajará:

class Sub
{
public:
    int operator [](size_t nIndex)
    {
        return 0;
    }   
};

int main()
{
    Sub s;
    s[0];
    0[s]; // ERROR 
}

Dado que no tenemos acceso a int class, esto no se puede hacer:

class int
{
   int operator[](const Sub&);
};

Respondido el 09 de diciembre de 15 a las 18:12

class Sub { public: int operator[](size_t nIndex) const { return 0; } friend int operator[](size_t nIndex, const Sub& This) { return 0; } }; - ben voigt

¿De verdad ha intentado compilarlo? ¡Hay un conjunto de operadores que no se pueden implementar fuera de la clase (es decir, como funciones no estáticas)! - Ajay

Ups, tienes razón. "operator[] será una función miembro no estática con exactamente un parámetro ". Estaba familiarizado con esa restricción en operator=, no creí que se aplicara a []. - ben voigt

Por supuesto, si cambia la definición de [] operador, nunca volvería a ser equivalente ... si a[b] es igual a *(a + b) y cambias esto, tendrás que sobrecargar también int::operator[](const Sub&); y int no es una clase ... - luis colorado

Esto ... no es ... C. - MD XF

Tiene muy buena explicacion en TUTORIAL SOBRE PUNTEROS Y ARRAYES EN C por Ted Jensen.

Ted Jensen lo explicó como:

De hecho, esto es cierto, es decir, dondequiera que se escriba a[i] se puede reemplazar con *(a + i) sin ningún problema. De hecho, el compilador creará el mismo código en cualquier caso. Por tanto, vemos que la aritmética de punteros es lo mismo que la indexación de matrices. Cualquiera de las dos sintaxis produce el mismo resultado.

Esto NO significa que los punteros y las matrices sean lo mismo, no lo son. Solo estamos diciendo que para identificar un elemento dado de una matriz tenemos la opción de dos sintaxis, una usando indexación de matriz y la otra usando aritmética de puntero, que arrojan resultados idénticos.

Ahora, mirando esta última expresión, parte de ella ... (a + i), es una suma simple que usa el operador + y las reglas de C establecen que dicha expresión es conmutativa. Es decir (a + i) es idéntico a (i + a). Así podríamos escribir *(i + a) tan fácilmente como *(a + i). Pero *(i + a) podría haber venido de i[a] ! De todo esto surge la curiosa verdad de que si:

char a[20];

la escritura

a[3] = 'x';

es lo mismo que escribir

3[a] = 'x';

Respondido el 13 de enero de 17 a las 06:01

a + i NO es una simple suma, porque es aritmética de punteros. si el tamaño del elemento de a es 1 (char), entonces sí, es como entero +. Pero si es (por ejemplo) un número entero, entonces podría ser equivalente a + 4 * i. - Alex Brown

@AlexBrown Sí, es aritmética de punteros, que es exactamente la razón por la que su última oración es incorrecta, a menos que primero convierta 'a' en un (char *) (asumiendo que un int tiene 4 caracteres). Realmente no entiendo por qué tanta gente se está obsesionando con el resultado del valor real de la aritmética de punteros. Todo el propósito de la aritmética de punteros es abstraer los valores de punteros subyacentes y dejar que el programador piense en los objetos que se manipulan en lugar de en los valores de dirección. - jschultz410

Sé que la pregunta está respondida, pero no pude resistirme a compartir esta explicación.

Recuerdo los principios del diseño del compilador, supongamos a es un int matriz y tamaño de int es de 2 bytes y la dirección base para a es 1000.

¿Cómo a[5] funcionará ->

Base Address of your Array a + (5*size of(data type for array a))
i.e. 1000 + (5*2) = 1010

¿Entonces

De manera similar, cuando el código c se divide en un código de 3 direcciones, 5[a] se convertirá en ->

Base Address of your Array a + (size of(data type for array a)*5)
i.e. 1000 + (2*5) = 1010 

Entonces, básicamente, ambas declaraciones apuntan a la misma ubicación en la memoria y, por lo tanto, a[5] = 5[a].

Esta explicación es también la razón por la que los índices negativos en matrices funcionan en C.

es decir, si accedo a[-5] me va a dar

Base Address of your Array a + (-5 * size of(data type for array a))
i.e. 1000 + (-5*2) = 990

Me devolverá el objeto en la ubicación 990.

respondido 29 nov., 16:01

En matrices C, arr[3] y 3[arr] son iguales, y sus notaciones de puntero equivalentes son *(arr + 3) a *(3 + arr). Pero por el contrario [arr]3 or [3]arr no es correcto y dará lugar a un error de sintaxis, ya que (arr + 3)* y (3 + arr)* no son expresiones válidas. La razón es que el operador de desreferencia debe colocarse antes de la dirección que proporciona la expresión, no después de la dirección.

Respondido el 11 de enero de 21 a las 19:01

en el compilador c

a[i]
i[a]
*(a+i)

¡Hay diferentes formas de referirse a un elemento en una matriz! (NO ES EN ABSOLUTO)

Respondido 29 Oct 14, 09:10

Un poco de historia ahora. Entre otros lenguajes, BCPL tuvo una influencia bastante importante en el desarrollo temprano de C. Si declaró una matriz en BCPL con algo como:

let V = vec 10

que en realidad asignó 11 palabras de memoria, no 10. Normalmente, V era la primera y contenía la dirección de la palabra inmediatamente siguiente. Entonces, a diferencia de C, nombrar V fue a esa ubicación y tomó la dirección del elemento cero de la matriz. Por lo tanto, la indirección de arreglos en BCPL, expresada como

let J = V!5

realmente tenía que hacer J = !(V + 5) (usando la sintaxis BCPL) ya que era necesario buscar V para obtener la dirección base de la matriz. Por lo tanto V!5 y 5!V eran sinónimos. Como observación anecdótica, WAFL (Warwick Functional Language) fue escrito en BCPL, y en lo mejor de mi memoria tendía a usar la última sintaxis en lugar de la primera para acceder a los nodos utilizados como almacenamiento de datos. De acuerdo, esto es de hace entre 35 y 40 años, por lo que mi memoria está un poco oxidada. :)

La innovación de prescindir de la palabra adicional de almacenamiento y hacer que el compilador insertara la dirección base de la matriz cuando se nombró llegó más tarde. Según el artículo de historia de C, esto sucedió aproximadamente en el momento en que se agregaron las estructuras a C.

Tenga en cuenta que ! en BCPL era tanto un operador de prefijo unario como un operador de infijo binario, en ambos casos haciendo indirección. solo que la forma binaria incluía una suma de los dos operandos antes de realizar la indirección. Dada la naturaleza orientada a palabras de BCPL (y B), esto en realidad tenía mucho sentido. La restricción de "puntero y entero" se hizo necesaria en C cuando ganó tipos de datos, y sizeof se convirtió en una cosa.

Respondido 08 Abr '19, 19:04

Bueno, esta es una característica que solo es posible debido al soporte de idiomas.

El compilador interpreta a[i] as *(a+i) y la expresion 5[a] evalúa a *(5+a). Dado que la suma es conmutativa, resulta que ambos son iguales. Por lo tanto, la expresión se evalúa como true.

Respondido 02 Abr '18, 19:04

Aunque redundante, es claro, conciso y breve. - Bill K

C ª

 int a[]={10,20,30,40,50};
 int *p=a;
 printf("%d\n",*p++);//output will be 10
 printf("%d\n",*a++);//will give an error

puntero p es una "variable", nombre de matriz a es un "mnemónico" o "sinónimo", por lo que p++ es válido pero a++ es inválido.

a[2] es igual a 2[a] porque la operación interna en ambos es "Aritmética de puntero" calculada internamente como *(a+2) iguales *(2+a)

respondido 07 nov., 20:03

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.