Этот вопрос впервые был вызван (неожиданными) результатами этого кода:
uint16_t t16 = 0;
uint8_t t8 = 0x80;
uint8_t t8_res;
t16 = (t8 << 1);
t8_res = (t8 << 1);
printf("t16: %x\n", t16); // Expect 0, get 0x100
printf(" t8: %x\n", t8_res); // Expect 0, get 0
Но, оказывается, это имеет смысл:
6.5.7 Операторы побитового сдвига
Ограничения
2 Каждый из операндов должен иметь целочисленный тип
Таким образом, первоначально запутанная строка эквивалентна:
t16 = (uint16_t) (((int) t8) << 1);
Немного не интуитивно понятное ИМХО, но, по крайней мере, четко определено.
Хорошо, отлично , но затем мы делаем:
{
uint64_t t64 = 1;
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x80000000, get 0x80000000
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x0, get 0x4000000000000000
}
// редактируем: следуя тому же буквальному аргументу, что и выше, следующее должно быть эквивалентно:
t64 = (uint64_t) (((int) t64) << 31);
// отсюда мое замешательство / ожидание [end_edit]
Теперь мы получаем интуитивный результат , но не то, что было бы получено из моего (буквального) прочтения стандарта. Когда и как происходит это "дальнейшее автоматическое продвижение типа"? Или есть ли где-то ограничение, что тип никогда не может быть понижен в должности (что имело бы смысл? ), в таком случае, как применяются правила продвижения для:
uint32_t << uint64_t
Поскольку в стандарте сказано, что оба аргумента повышаются до типа int; должны ли оба аргумента здесь быть повышены до одного типа?
// edit:
Более конкретно, что должно получиться в результате:
uint32_t t32 = 1;
uint64_t t64_one = 1;
uint64_t t64_res;
t64_res = t32 << t64_one;
// end edit
Ответ на вышеупомянутый вопрос будет решен, когда мы узнаем, что спецификация не требует повышения до int
, а точнее целочисленного типа
, который определяется как uint64_t.
// УТОЧНЕНИЕ РЕДАКТИРОВАНИЕ:
Хорошо, но теперь я снова запутался.В частности, если uint8_t
является целочисленным типом, то почему он вообще повышается до int
? Похоже, что это не связано с константой int 1, как демонстрирует следующее упражнение:
{
uint16_t t16 = 0;
uint8_t t8 = 0x80;
uint8_t t8_one = 1;
uint8_t t8_res;
t16 = (t8 << t8_one);
t8_res = (t8 << t8_one);
printf("t16: %x\n", t16);
printf(" t8: %x\n", t8_res);
}
t16: 100
t8: 0
Почему продвигается выражение (t8 << t8_one), если uint8_t является целочисленным типом?
-
Для ссылка, я работаю с ISO / IEC 9899: TC9, WG14 / N1124 6 мая 2005 года. Если это устарело и кто-то может также предоставить ссылку на более новую копию, это тоже будет признательно.