Если вы установите указатель на адрес переменной, а затем выполните разыменование, вы измените значение на указателе, а не на сам адрес.Так что если вы пишете ip += 1
, который меняет адрес, а *ip +=1
меняет значение по адресу.
Вот несколько примеров, которые должны помочь прояснить, как работают указатели, в том числе со значениями с плавающей запятой.Вы должны прочитать о представлении IEEE754 32-разрядных чисел с плавающей точкой, чтобы лучше понять, почему 1.0
представляется как 0x3f800000
.
Обратите внимание, что этот код делает много предположений о размерах типов (которые являются реализациейопределены!) и игнорирует правила псевдонимов (нельзя указывать на объект в памяти с типом указателя, который не соответствует объявленному типу объекта, а затем разыменовывать этот указатель).Тем не менее, на практике вы всегда можете интерпретировать любую память как биты, даже если она «небезопасна» или «незаконна».
int x = 0;
int* ip = &x;
*ip += 1; // x = 1
ip += 1; // ip is now increased by sizeof(int) and probably points to
// the gap in the stack between x and ip, since sizeof(x) is probably 4
// and ip is probably 8 byte aligned
ip += 1; // now ip probably points to itself! (the address points to its own address value)
ip -= 2; // now ip points to x again
*ip += 2; // now x = 3
float *fp = (float*)ip; // the value *fp is the same in binary, 0b11
int z = *(int *)fp; // z is 3, because we're preventing the conversion
*fp = 1.0; // in hex, *fp is 0x3f800000
int y = *fp; // 1.0 is converted to int and stored in y as 1
int a = *(int *)fp; // a is 0x3f800000