изменение значения короткой переменной с помощью указателя char

Код:

int main(){
   short a=1;         // #1
   char *p=(char*)&a;
   *(p)=1;            // #2
   cout << a << endl; // Output: 1
   *(p+1)=2;          // #3
   cout << a << endl; // Output: 513
}

Насколько я понимаю, вывод должен быть таким, как показано на рисунке ниже, 257, а затем 258.
Есть ли какая-то причина, по которой я получаю другой результат при запуске программы выше?

введите здесь описание изображения

Обновление: я знаю, что это поведение Undefined, но тем не менее означает ли это, что преобразование десятичного числа в двоичное выполняется не как обычно: справа налево, а вместо этого выполняется слева направо, например:

binary(a)=1000 0000 | 0000 0000


поэтому *(p)=1; создаст binary(a)=1000 0000 | 0000 0000, что равно 1 в десятичной системе
, а *(p+1)=2; создаст binary(a)=1000 0000 | 0100 0000, что будет 513
что точно соответствует результату программы.


person AlexDan    schedule 08.12.2012    source источник
comment
en.wikipedia.org/wiki/Endianness   -  person Benjamin Lindley    schedule 09.12.2012
comment
@BenjaminLindley скорее en.wikipedia.org/wiki/Undefined_behavior   -  person    schedule 09.12.2012
comment
Проще говоря, эти байты (вероятно) переключаются. Вы не можете точно сказать о неопределенном поведении, но, скорее всего. Имея это в виду, вы фактически устанавливаете левый байт равным 2, а правый — 1 (256*2 + 1 = 513).   -  person chris    schedule 09.12.2012
comment
@ H2CO3: это может быть неопределенное поведение в отношении стандарта, и об этом обязательно следует упомянуть. Но все мы знаем, что происходит на самом деле, и это тоже следует упомянуть.   -  person Benjamin Lindley    schedule 09.12.2012
comment
@BenjaminLindley (Конечно. Но когда я говорю то же самое, меня всегда отговаривают...)   -  person    schedule 09.12.2012
comment
@chris Я обновил свой вопрос, не могли бы вы сказать мне, верна ли моя интерпретация.   -  person AlexDan    schedule 09.12.2012
comment
Обратите внимание, что порядок следования байтов влияет на порядок байтов в многобайтовом типе. Это не обязательно влияет на порядок битов в байте. Но это невозможно обнаружить, поскольку вы не можете адресовать что-то меньшее, чем байт. Но в остальном да, ваша интерпретация верна.   -  person Benjamin Lindley    schedule 09.12.2012
comment
@chris Спасибо за вашу поддержку :)   -  person    schedule 09.12.2012


Ответы (2)


То, что здесь происходит, связано с тем, что у нас есть 2-байтовый short в архитектуре процессора с прямым порядком байтов. Стандарт не требует, чтобы архитектура была LE, поэтому в любом случае эта программа может генерировать различные результаты при запуске на разных системах.

short здесь размещается в памяти с младшим значащим байтом (LSB) первым:

         Memory addresses ------>
            LSB          MSB

         0000 0000   0000 0000

p указывает на младший бит и устанавливает значение 1:

         0000 0001   0000 0000

Результат при интерпретации как short будет LSB + 256 * MSB, т.е. 1 + 0 * 256 = 1

Затем p указывает на MSB (который находится на следующем адресе памяти) и устанавливает его в 2:

         0000 0001   0000 0010

Результат при интерпретации как short: 1 + 2 * 256 = 513

person Jon    schedule 08.12.2012
comment
так, например, оператор сдвига вправо переместит 1 в LSB вправо, а 1 в MSB влево, поэтому cout ‹‹ (a››1); выведет 0000 0000 0000 0001, что равно 256. Это правильно? - person AlexDan; 09.12.2012
comment
@AlexDan: Нет, неправильно. Сдвиг левого и правого битов хорошо определен, переносим. (1››1) == 0. Независимо от порядка байтов в вашей системе. - person Benjamin Lindley; 09.12.2012

Есть ли какая-то причина, по которой я получил другой результат, когда запускаю программу выше?

Да. Ответ, не зависящий от языка: потому что эта программа вызывает неопределенное поведение. Ответьте с учетом того, что могло произойти на самом деле: ваша система имеет другой порядок следования байтов, чем вы думаете.

person Community    schedule 08.12.2012