Почему uint16_t имеет значение здесь? - PullRequest
13 голосов
/ 23 мая 2011
volatile uint16_t r;
unsigned char poly = 0x07;
unsigned char c = 0;

r = (c << 8) ^ poly;

Когда код компилируется с помощью gcc в Linux, r равен 7.
Когда тот же код компилируется с помощью Microchip C18, r равен 0.
Почему?

Если я изменю его на:

volatile uint16_t r;
uint16_t poly = 0x07;
uint16_t c = 0;

r = (c << 8) ^ poly;

r становится также 7 в C18.

В руководстве по C18 есть раздел о целочисленном продвижении, но я не думаю, что это как-то связано с моим вопросом.В любом случае, вот оно:

ISO предписывает, чтобы вся арифметика выполнялась с точностью int или выше.По умолчанию MPLAB C18 будет выполнять арифметику с размером наибольшего операнда, даже если оба операнда меньше целого.Обязательное поведение ISO можно установить с помощью параметра командной строки -Oi.

Ответы [ 2 ]

3 голосов
/ 23 мая 2011

Поскольку c << 8 не определено в этом компиляторе, результат xor не может быть предсказан. Результатом может быть все, что выберет компилятор.

См. Что должен знать каждый программист на Си о неопределенном поведении для ознакомления с неопределенным поведением, особенно с разделом "Величины слишком больших сдвигов".

2 голосов
/ 23 мая 2011

c << 8 с c a char в основном отправляет все биты в забвение. Как указано в документе, и c, и 8 вписываются в char, поэтому все делается с использованием char. </p>

c << 8UL может изменить сделку. </p>

...