Arduino левый сдвиг не работает, как ожидалось, ошибка компилятора?

0
uint32_t a = 0xFF << 8;
uint32_t b = 0xFF;
uint32_t c = b << 8;

Я компилирую для Uno (1.0.x и 1.5), и было бы очевидно, что "a" и "c" должны быть одинаковыми, но они не... по крайней мере, не при запуске на цель. Я компилирую тот же код на хосте и не имею никаких проблем.

Правая смена работает нормально, сдвиг влево работает только тогда, когда я изменяю переменную в сравнении с константой.

Может ли кто-нибудь подтвердить это?

Я использую Visual Micro с VS2013. Компиляция с результатом 1.0.x или 1.5 arduino приводит к тому же отказу.

[РЕДАКТИРОВАТЬ]

На цель: A = 0xFFFFFF00 C = 0x0000FF00

  • 0
    Каковы их ценности?
  • 2
    Какой целочисленный размер по умолчанию для рассматриваемой платформы? b присваивается 32-битное значение при присваивании, поэтому, когда вы сдвигаете его влево позже, не возникает вопроса о переполнении. Если число умалчиваемого размера был 8 бит , то назначение переполнится. a
Показать ещё 5 комментариев
Теги:
arduino
arduino-uno

2 ответа

1
Лучший ответ

Проблема связана с подписанным/неподписанным неявным литьем.

С uint32_t a = 0xFF << 8; ты имеешь в виду

  • 0xFF; это signed char;
  • Существует операция <<, поэтому переменная преобразуется в int. Поскольку это был подписанный символ (и поэтому его значение было -1), оно дополняется символом 1, чтобы сохранить знак. Таким образом, переменная равна 0xFFFFFFFF;
  • он смещается, поэтому a = 0xFFFFFF00.

Если вы хотите воспроизвести одно и то же поведение, попробуйте этот код:

uint32_t a = 0xFF << 8;
uint32_t b = (signed char)0xFF;
uint32_t c = b << 8;

Serial.println(a, HEX);
Serial.println(b, HEX);
Serial.println(c, HEX);

В результате

FFFFFF00
FFFFFFFF
FFFFFF00

Или, наоборот, если вы пишете

uint32_t a = (unsigned)0xFF << 8;

вы получите, что a = 0x0000FF00.

В компиляторе есть только две странные вещи:

  1. uint32_t a = (unsigned char)0xFF << 8; возвращает a = 0xFFFFFF00
  2. uint32_t a = 0x000000FF << 8; возвращает a = 0xFFFFFF00.

Возможно, это неправильный перевод в компиляторе....

  • 2
    Странные вещи, которые вы указали 1 и 2, это то, что озадачивало и было неожиданным, но, по крайней мере, обходным. Спасибо всем.
  • 0
    С компилятором все в порядке. 0xFF - это int без signed char . Целочисленные литералы должны быть int , long int или long long int . Поскольку int имеет ширину 16 бит в Arduino, 0xFF << 8 будет отрицательным. Поэтому результат будет 0xFFFFFF00 вместо 0xFFFFFFFF. Только после приведения к (signed char)0xFF оно станет 0xFFFFFFFF. Даже «странные вещи» выше тоже правильно. Просто вы не знаете как стандарт C, так и компилятор.
Показать ещё 1 комментарий
0

[Кредит идет Мацу Петерсону]

Использование оператора трансляции, чтобы заставить компилятор обрабатывать 0xFF как uint32_t, решает проблему. Похоже, что Arduino xcompiler рассматривает константы немного по-другому, так как я никогда не делал их перед сменой.

Благодарю!

  • 0
    нет ничего плохого в компиляторе. Стандарт C определяет, что 0xFF будет иметь тип int (который имеет ширину 16 бит в Arduino), а 0xFF << 8 - отрицательное число. Кроме того, любые типы, меньшие чем int, должны быть преобразованы в int

Ещё вопросы

Сообщество Overcoder
Наверх
Меню