указатели — Странное преобразование адресов в C / C ++?

Не могу сказать, что плохо знаю C / C ++, но столкнулся с интересным синтаксисом.
У меня есть этот код:

int i=7;
char* m=(char*)&i;
m[2]=9;
cout<<i;

Его вывод 589831. Так может кто-нибудь подробно объяснить мне, что здесь происходит.

-1

Решение

Целое число i очень вероятно, занимает 4 байта, расположенных с самым низким значением первым (little-endian). В памяти значения выглядят так:

0x07 0x00 0x00 0x00

Вы изменили значение в индексе 2, теперь оно выглядит так:

0x07 0x00 0x09 0x00

Если вы перевернете байты и соедините их вместе, они получат шестнадцатеричное значение 0x00090007, которое равно 589831 в десятичном виде.

3

Другие решения

  1. 4-байтовое целое число заполняется числом 7.
  2. 4-байтовое целое число отображается в массив из четырех отдельных байтов (символов). В архитектуре с прямым порядком байтов, такой как x86, наименее значимые байты идут первыми в числе, поэтому массив выглядит в памяти следующим образом: { 07, 00, 00, 00 }
  3. 3-й байт массива байтов целочисленного слэша изменен на 9. Теперь он выглядит так: { 07, 00, 09, 00 }
  4. Полученное целое число (шестнадцатеричное 90007) записывается в стандартный вывод (в десятичном формате: 589831).

Короче говоря, это пример того, как вы можете манипулировать отдельными байтами в многобайтовом целом числе.

3

Вы приводите целочисленный адрес к char* затем изменив его с помощью записи массива. Этот шаг

m[2] = 9;

такой же, как арифметика указателя

*(m+2) = 9;

то есть, это изменение байта по адресу m + 2 байта. Таким образом, вы изменили один из байтов (3-й) в вашем начальном целочисленном значении

1

Вот мое объяснение происходящего, затем объяснение.

// An integer on the stack, probably 4 bytes big, but we can't say that for sure.
int i=7; // Looks like 0x0000007 in memory. Endianness needs to be considered.

// Treat that integer as a \0 terminated string.
char* m=(char*)&i; // Acts as an empty string since the first byte is a 0, but we can't count on that.

// Set the second byte to 9.
m[2]=9; // Results in i being 0x00090007 (589831 decimal) on whatever architecture you are running. Once again, can't count on it.

// Print the modified integer.
cout<<i;

Это невероятно опасная и глупая вещь по трем причинам …

  1. Вы не должны рассчитывать на порядок байт вашей архитектуры. Ваш код может в конечном итоге работать на процессоре, который имеет другое представление о том, что int является.

  2. Вы не можете рассчитывать на int всегда быть 4 байта.

  3. Теперь у вас есть char* что если вы когда-нибудь будете выполнять строковую операцию, это может привести к сбою. В вашем конкретном случае он напечатает пустую строку, но это не займет много времени, чтобы это целое число не содержало 0 байт и продолжало читать другие части вашего стека.

если ты действительно очень необходимо сделать это, предпочтительный метод заключается в использовании союзы но этот вид небольшого изменения очень склонен к ошибкам, и профсоюзы делают очень мало, чтобы помочь.

1

int i=7 резервирует 4 байта памяти для целых чисел и в зависимости от архитектуры процессора (допустим, у вас i86) будет производить что-то подобное в памяти
7 0 0 0

затем указатель m создан, чтобы указывать на начало 7 0 0 0 ,
после m[2] = 9 память должна выглядеть
7 0 9 0 (массивы начинаются с нуля);

тогда вы распечатываете я

0
По вопросам рекламы [email protected]