Побитовые операции над типами перечислений - PullRequest
4 голосов
/ 02 мая 2011

При попытке прочитать данные из памяти в перечисление с помощью следующего кода я получил странные результаты:

void read_memory (const unsigned, const unsigned, unsigned* const);

/* ... */

enum {DATA_0, DATA_1, DATA_2} data;
read_memory(base_addr, offset, &data);  //data = 0x0900
data >>= 8;  //data = 0x7e000000

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

Прежде всего, я знаю, что стандарт не требует определенной ширины для перечисляемых типов, пока все членымогут быть представлены.Фактически, 6.7.2.2 утверждает, что:

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

Но поскольку необработанные данные, считанные из памяти, помещаются в символ, я думаю, что это не должно быть проблемой.Более того, если я правильно понимаю, «совместимый» означает, что вы можете использовать его, как если бы он был такого типа.В частности, объекты перечислимого типа могут быть операндами побитовых операторов сдвига.Я также знаю, что подпись может быть проблемой, поскольку мы не знаем, подписаны ли enum или нет.Но, насколько я могу судить, 0x0900, похоже, не подписан.

Так в чем же проблема?

Ответы [ 3 ]

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

Сколько данных читает ваша (на мой взгляд, плохо названная) read_memory() функция?Если это не то же самое, что значение sizeof data, у вас есть проблема.То, что перечисленные значения достаточно малы для char, не означает, что компилятор имеет для выбора одного char;возможно, инструкции по работе с числами int быстрее и / или есть проблемы с выравниванием.

0 голосов
/ 09 января 2017

Типы перечислений подписаны, поэтому при сдвиге бит знака (1) копируется в числовые биты.

0 голосов
/ 16 мая 2011

После тестирования кода вне отладчика выяснилось, что он вел себя правильно, и информация, отображаемая gdb, была неточной.

Фактически, анализ разобранного машинного кода показал, что он не совпадаетC исходные номера строк.В результате эпилог функции считался (gdb) частью инструкции data >>= 8;.Эта проблема остается для меня странной, так как я скомпилировал и связал все исходные и объектные файлы с -g -O0.

Возможно, ошибка в компиляторе ...

Редактировать: На самом деле это не имеет ничего общегов gdb ошибочные были символы отладки, выдаваемые компилятором.

...