Здесь вам не хватает неявного преобразования типов из-за целочисленных правил продвижения, применяемых при передаче аргументов в printf
.
Возможно, вы заметили, что вы можете напечатать char
, short int
или long int
с использованием той же строки формата "% d" .Это стало возможным благодаря тому, что все необязательные аргументы printf
подвергаются продвижению по умолчанию.Фактически, так обстоит дело с аргументами всех функций с переменными числами !
Упрощенная сумма правил продвижения выглядит так:
- Плавающие становятсяdouble
- Целочисленные типы, меньшие чем int (то есть, символы и короткие целые числа), становятся int
- Без знака int остается как беззнаковое int
Это означает, что существуетздесь скрытое преобразование, которое не очень очевидно, если вы его не ищете.
Случай 1:
_tmpSig = (uint32)rawTCU;
Здесь, поскольку мы конвертируем из типа со знаком ,расширение знака выполняется так, что _tmpSig
становится очень большим числом без знака, которое является представлением -100
.
Теперь, при вызове printf
, никакого продвижения не происходит, так как это уже unsigned int
,При печати, поскольку вы использовали форматирование "% d", оно интерпретируется как signed int
и дает -100.
Случай 2:
_tmpSig = (uint16)rawTCU;
После этого _tmpSig
теперь содержит неподписанный короткий int.Расширение знака здесь не требуется, поскольку оно приведено к типу того же размера.Таким образом, в представлении нет никаких изменений.
Однако, когда оно передается в printf()
, оно превращается в signed int
.Так что здесь есть скрытое преобразование из unsigned short
в signed long
.Поскольку мы конвертируем из типа без знака , здесь нет расширения знака!Это где значение на самом деле становится 65436 .Теперь при печати как «% d» печатается то же значение.
РЕДАКТИРОВАТЬ: Исправлена фактическая неточность, указанная @ EricPostpischil