c стандарт и битовые сдвиги

Этот вопрос впервые был вызван (неожиданными) результатами этого кода:

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 года. Если это устарело и кто-то может также предоставить ссылку на более новую копию, это тоже будет признательно.

5
задан Pat 31 October 2011 в 00:10
поделиться