Здравствуйте, enji, Вы писали:
E>Собрал тут gcc5.2 arm-none-eabi, начал падать на следующем коде E>
E>#define r_char_bits CHAR_BIT
E>#define r_digits(_Tp, S) (sizeof(_Tp) * r_char_bits - S)
E>#define r_min_0(_Tp) ((_Tp)0)
E>#define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
E>#define r_min(_Tp, S) r_min_##S(_Tp)
E>static const signed char min2 = r_min(signed char, 1); // это компиляется
E>struct Test {
E> static const signed char min2 = r_min(signed char, 1); // а это - нет
E>};
E>
E>error: left operand of shift expression '(-2ll << 6u)' is negative E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
E>Сыроват еще 5.2? Или я как-то криво собрал? Или тут реально какая-то ошибка в коде?
E>Кто-нить может проверить у себя на 5.2?
У вас там действительно ошибка, сдвиг целого со знаком числа,
определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде,
возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?
Z>Собрал без ошибок.
Z>У вас там действительно ошибка, сдвиг целого со знаком числа, Z>определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде, Z>возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?
А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...
Z>>Собрал без ошибок.
Z>>У вас там действительно ошибка, сдвиг целого со знаком числа, Z>>определен только если оно больше или равно нулю, т.е. у вас UB в чистом виде, Z>>возможно у вас включен режим предупреждения==ошибки, поэтому и возникает ошибка компиляции?
E>А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...
В первоначальном сообщении '(-2ll << 6u)', а вот как он это получил фиг знает,
здесь надо смотреть опции компилятора.
Здравствуйте, Zhendos, Вы писали:
E>>А где тут целое со знаком? -(1 << 6) * 2 вообще то говоря...
Z>В первоначальном сообщении '(-2ll << 6u)', а вот как он это получил фиг знает, Z>здесь надо смотреть опции компилятора.
угу, он в это раскрыл. А вот почему — неясно. Причем если убрать struct, то раскроет нормально
E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
Раскрыл бы сразу макросы сам. Зачем всех заставлять через них продираться? Не в макросах же проблема. И заменить выражение на что-нибудь попроще, собрав минимальный пример, навроде такого:
struct Test {
static const int foo = (1 << sizeof(int))*(-3);
};
E>Сыроват еще 5.2?
Да, похоже на баг.
Причём проблема исчезает если не использовать inline инициализацию, либо если убрать sizeof, либо если использовать старый стандарт. Про последнее как раз понятно, что в C++11 поменялись правила левого сдвига знаковых чисел и там стоит повнимательней на код посмотреть.
Ну либо, обойти проблему, использовав в коде беззнаковый тип для левого операнда — это работает везде одинаково.
Здравствуйте, watchmaker, Вы писали:
W>Раскрыл бы сразу макросы сам.
Я раскрыл до до -(1ll << 6) * 2 — не падал. Не дошло, что дело в sizeof.
Причем неясно, каким боком тут struct, если просто сделать глобальный static const — все ок.
W>Ну либо, обойти проблему, использовав в коде беззнаковый тип для левого операнда — это работает везде одинаково.
да, заменил на 1ULL — завелось. Спасибо!
Но похоже стоит пока остаться на 4.х ветке, счас попробую собрать 4.9.3
Здравствуйте, watchmaker, Вы писали:
W>Здравствуйте, enji, Вы писали:
E>> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2)) W>Раскрыл бы сразу макросы сам. Зачем всех заставлять через них продираться? Не в макросах же проблема. И заменить выражение на что-нибудь попроще, собрав минимальный пример, навроде такого:
struct Test {
W> static const int foo = (1 << sizeof(int))*(-3);
W>};
Здравствуйте, enji, Вы писали:
E>error: left operand of shift expression '(-2ll << 6u)' is negative E> #define r_min_1(_Tp) ((_Tp)(-(1LL << (r_digits(_Tp, 1)-1))*2))
Это фича: нельзя в константных выражениях сдвигать знаковые отрицательные значения.
Если я не ошибаюсь, это полностью соответствует последней версии стандарта.