2009-04-29 11 views
11

decir que tenemos el siguiente código:C dirección de gama confusión

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 compilan y ejecutan los resultados son de la siguiente manera:

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

entiendo el resultado de & E [2] cuales es 8 más la dirección de la matriz, ya que está indexada por 2 y de tipo int (4 bytes en mi sistema de 32 bits), pero no puedo 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 entero?

Me pregunto si es el sistema de tipo C (un poco de fundición) lo que hace esta peculiaridad?

+0

Esto es casi un duplicado del http://stackoverflow.com/questions/759663/pointer-arithmetic-in-c – finnw

+0

¿Qué hay de printf ("E: 0x% x \ n", &a); – dashesy

Respuesta

10

Hay que recordar lo que la expresión a[2] realmente significa: . 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 del puntero tiene en cuenta el tipo de objeto señalado. Pero eso se soluciona detrás de escena. Simplemente tiene que usar compensaciones naturales en sus matrices y todos los detalles funcionan.

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

Debajo del 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. Expone ese detalle en sus dos impresiones de las direcciones.

+1

... o 2 ["gracioso"]. –

8

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 una cantidad de bytes, transfiera las direcciones a char *.

5

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

Para responder a su pregunta "actualización", una vez más puntero de la aritmética (esta vez además puntero) se está realizando. Se hace de esta manera en C para facilitar el "índice" de un fragmento de datos contiguos señalados por el puntero.

+1

El valor de retorno es un int, no un int *. – paxdiablo

+0

Lo siento, momento rubio ... tienes razón. – marcog

2

Usted puede estar interesado en Pointer Arithmetic In C preguntas y respuestas.

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

0

Si quieres ver la diferencia de bytes, tendrá a un tipo que es de 1 byte en tamaño, así:

printf("&E[2]-E:\t0x%x\n",(char*)(&a[2])-(char*)(&a[0])) 
1

Cuando suma y resta de punteros en C, se utiliza el tamaño de el tipo de datos en lugar de las direcciones absolutas.

Si usted tiene un puntero int y agregar el número 2 a la misma, se 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 utilizando el tamaño del tipo de datos es muy conveniente, de manera que, por ejemplo, puede simplemente usar p++ en lugar de tener que especificar el tamaño del tipo cada vez que:. p+=sizeof(int))

7

Cuando incrementa el puntero en 1 (p + 1) y luego el puntero apunta a la siguiente dirección válida agregando (p + sizeof (Type)) bytes a p. (Si el tipo es int entonces p + sizeof (int))

lógica similar es válido para p-1 también (por supuesto restar en este caso).

Si sólo se aplican esos principios aquí:

En términos simples:

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

Así, detrás de la escena,

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

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

número entero. por la misma razón que el: Hoy - 1 de abril = número. No fecha

+0

elegante de hecho. – Pwn