Беззнаковое длинное и битовое смещение - PullRequest
7 голосов
/ 09 мая 2011

У меня проблема со сдвигом битов и длинными без знака.Вот мой тестовый код:

char header[4];
header[0] = 0x80;
header[1] = 0x00;
header[2] = 0x00;
header[3] = 0x00;

unsigned long l1 = 0x80000000UL;
unsigned long l2 = ((unsigned long) header[0] << 24) + ((unsigned long) header[1] << 16) + ((unsigned long) header[2] << 8) + (unsigned long) header[3];

cout << l1 << endl;
cout << l2 << endl;

Я ожидал бы, что l2 также будет иметь значение 2147483648, но вместо этого он печатает 18446744071562067968. Я предполагаю, что смещение битов первого байта вызывает проблемы?

Надеюськто-нибудь может объяснить, почему это не удается, и как я могу изменить вычисление l2, чтобы оно возвращало правильное значение.

Заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 09 мая 2011

Ваше значение 0x80, хранящееся в символе, является подписанным количеством. Когда вы преобразуете его в более широкий тип, значение расширяется со знаком, чтобы сохранить то же значение, что и у более крупного типа.

Измените тип char в первой строке на unsigned char, и вы не получите расширение знака.

Чтобы упростить то, что происходит в вашем случае, запустите:

char c = 0x80
unsigned long l = c
cout << l << endl;

Вы получите этот вывод:

18446744073709551488

, что равно -128 как 64-разрядное целое число (0x80 равно -128 как 8-разрядное целое число).

2 голосов
/ 09 мая 2011

Тот же результат здесь (Linux / x86-64, GCC 4.4.5).Поведение зависит от размера unsigned long, который равен как минимум 32 бита, но может быть больше .

Если вы хотите ровно 32 бита, используйтеuint32_t вместо (из заголовка <stdint.h>; не в C ++ 03, но в готовящемся стандарте и широко поддерживается).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...