Por qué un puntero + 1 agrega 4 en realidad

#include int main(void){ int *ptr,a,b; a = ptr; b = ptr + 1; printf("the vale of a,b is %x and %x respectively",a,b); int c,d; c = 0xff; d = c + 1; printf("the value of cd are %x and %x respectively",c,d); return 0; } 

el valor de salida es

 the vale of a,b is 57550c90 and 57550c94 respectively the value of cd are ff and 100 respectively% 

Resulta que el ptr + 1 en realidad, ¿por qué se comporta de esta manera?

Considera lo que es un puntero … es una dirección de memoria. Cada byte en memoria tiene una dirección. Entonces, si tiene un int que es de 4 bytes y su dirección es 1000, 1001 es en realidad el segundo byte de ese int y 1002 es el tercer byte y 1003 es el cuarto. Dado que el tamaño de un int puede variar de comstackdor a comstackdor, es imperativo que cuando incremente su puntero no obtenga la dirección de algún punto medio en el int . Por lo tanto, el trabajo de averiguar cuántos bytes omitir, en función de su tipo de datos, se maneja por usted y puede usar el valor que obtenga y no preocuparse por ello.

Como señala Basile Starynkvitch, esta cantidad variará dependiendo de la propiedad sizeof del miembro de datos al que se apunta. Es muy fácil olvidar que aunque las direcciones son secuenciales, los indicadores de sus objetos deben tener en cuenta el espacio de memoria real requerido para albergar esos objetos.

Debido a que los punteros están diseñados para ser compatibles con matrices:

 *(pointer + offset) 

es equivalente a

 pointer[offset] 

Por lo tanto, Pointer Aritmetic no funciona en términos de bytes, sino en términos de tamaño de sizeof(pointer base type) bloques de tamaño bytes.

Deberías tomarte tiempo para leer un buen libro de lenguaje de progtwigción en C (como K&R “el lenguaje de progtwigción en C” )

La aritmética de punteros es un tema complicado. Una adición de puntero significa pasar a algún elemento puntiagudo siguiente. Así que la dirección se incrementa por el sizeof del elemento puntiagudo.

Respuesta corta

La dirección del puntero se incrementará por sizeof(T) donde T es el tipo al que se apunta. Así que para un int , el puntero se incrementará por sizeof(int) .

¿Por qué?

Bueno, ante todo, el estándar lo requiere. La razón por la que este comportamiento es útil (aparte de la compatibilidad con C) es porque cuando tiene una estructura de datos que utiliza memoria contigua, como una matriz o un std::vector , puede moverse al siguiente elemento de la matriz simplemente agregando uno al puntero. Si desea mover al elemento nth en el contenedor, simplemente agregue n.

Ser capaz de escribir firstAddress + 2 es mucho más simple que firstAddress + (sizeof(T) * 2) , y ayuda a prevenir los errores que surgen de los desarrolladores suponiendo que sizeof(int) es 4 (podría no serlo) y escribir código como firstAddress + (4 * 2) .

De hecho, cuando dices myArray[4] , estás diciendo myArray + 4 . Esta es la razón por la que los índices de matrices comienzan en 0; simplemente agrega 0 para obtener el primer elemento (es decir, myArray apunta al primer elemento de la matriz) y n para obtener el nth.

¿Qué pasa si quiero mover un byte a la vez?

Se garantiza que sizeof(char) tiene un tamaño de un byte, por lo que puede usar un char* si realmente desea mover un byte a la vez.

Se usa un puntero para apuntar a un byte específico de la marca de memoria donde se ha asignado un objeto (técnicamente puede apuntar a cualquier parte, pero es así como se usa). Cuando haces aritmética de punteros, opera en función del tamaño de los objetos apuntados. En su caso, es un puntero a enteros, que tienen un tamaño de 4 bytes cada uno.

Consideremos un puntero p . La expresión p+n es como (unsigned char *)p + n * sizeof *p (porque sizeof(unsigned char) == 1 ). Prueba esto :

 #include  #define N 3 int main(void) { int i; int *p = &i; printf("%p\n", (void *)p); printf("%p\n", (void *)(p + N)); printf("%p\n", (void *)((unsigned char *)p + N * sizeof *p)); return 0; }