Этот вопрос был впервые вдохновлен (неожиданными) результатами этого кода:
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
}
// edit: после того же буквального аргумента, что и выше, следующее должно быть эквивалентно:
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
, а точнее до integer type
, которое 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 является целочисленным типом? </p>
-
Для справки, я работаю с ISO / IEC 9899: TC9, WG14 / N1124 6 мая 2005 г. Если это устарело, и кто-то может также предоставить ссылку на более свежую версиюкопия, это также будет оценено.