Pregunta

Digamos que tenemos el siguiente código:

int main(){
    int a[3]={1,2,3};
    printf("      E: 0x%x\n", a);
    printf("  &E[2]: 0x%x\n", &a[2]);
    printf("&E[2]-E: 0x%x\n", &a[2] - a);
    return 1;
}

Cuando se compila y ejecuta, los resultados son los siguientes:

      E: 0xbf8231f8
  &E[2]: 0xbf823200
&E[2]-E: 0x2

Entiendo el resultado de & amp; E [2] que es 8 más la dirección del arreglo, ya que está indexado por 2 y de tipo int (4 bytes en mi sistema de 32 bits), pero ¿No puedes entender por qué la última línea es 2 en lugar de 8?

Además, ¿qué tipo de la última línea debería ser: un entero o un puntero de entero?

Me pregunto si es el sistema de tipo C (algo así como el casting) lo que hace esta peculiaridad.

¿Fue útil?

Solución

Tienes que recordar lo que realmente significa la expresión a [2] . Es exactamente equivalente a * (a + 2) . Tanto es así, que es perfectamente legal escribir 2 [a] en su lugar, con el mismo efecto.

Para que funcione y tenga sentido, la aritmética de punteros tiene en cuenta el tipo de cosa apuntada. Pero eso se cuida tras bambalinas. Puedes usar simplemente las compensaciones naturales en tus arreglos, y todos los detalles simplemente funcionan.

La misma lógica se aplica a las diferencias de puntero, lo que explica el resultado de 2 .

Bajo el capó, en su ejemplo, el índice se multiplica por sizeof (int) para obtener un desplazamiento de bytes que se agrega a la dirección base de la matriz. Expones ese detalle en tus dos impresiones de las direcciones.

Otros consejos

Al restar punteros del mismo tipo, el resultado es el número de elementos y no el número de bytes. Esto es por diseño para que pueda indexar fácilmente matrices de cualquier tipo. Si desea un número de bytes, envíe las direcciones a char *.

Cuando incrementa el puntero en 1 (p + 1), el puntero apuntaría a la siguiente dirección válida agregando (p + tamaño de (Tipo)) bytes a p. (Si el Tipo es int, entonces p + sizeof (int))

La lógica similar es válida también para p-1 (por supuesto, resta en este caso).

Si solo aplicas esos principios aquí:

En términos simples:

a[2] can be represented as (a+2)
a[2]-a      ==>  (a+2) - (a)    ==> 2

Entonces, detrás de la escena,

a[2] - a[0]  
==> {(a+ (2* sizeof(int)) ) - (a+0) }  / sizeof(int) 
==> 2 * sizeof(int) / sizeof(int) ==> 2

La línea & amp; E [2] -2 está haciendo la resta del puntero, no la resta de enteros. La resta del puntero (cuando ambos punteros apuntan a datos del mismo tipo) devuelve la diferencia de las direcciones dividida por el tamaño del tipo al que apuntan. El valor de retorno es un int.

Para responder a tu " actualización " Pregunta, una vez más se está realizando la aritmética del puntero (esta vez la adición del puntero). Se hace de esta manera en C para facilitar el " índice " una porción de datos contiguos apuntados por el puntero.

Puede estar interesado en Pointer Arithmetic en C preguntas y respuestas.

básicamente, los operadores + y - tienen en cuenta el tamaño del elemento cuando se usan en los punteros.

Al sumar y restar punteros en C, usa el tamaño del tipo de datos en lugar de las direcciones absolutas.

Si tiene un puntero int y le agrega el número 2, avanzará 2 * sizeof (int). De la misma manera, si resta dos punteros int, obtendrá el resultado en unidades de sizeof (int) en lugar de la diferencia de las direcciones absolutas.

(Tener punteros que utilicen el tamaño del tipo de datos es bastante conveniente, por lo que, por ejemplo, puede usar simplemente p ++ en lugar de tener que especificar el tamaño del tipo cada vez: p + = sizeof (int) .)

Re: " Además, ¿qué tipo de la última línea debería ser? ¿Un entero o un puntero de entero? "

un entero / numero de igual modo que el: Hoy - 1 de abril = número. no fecha

Si desea ver la diferencia de bytes, tendrá que utilizar un tipo que tenga un tamaño de 1 byte, como este:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0]))
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top