Страницы

Поиск по вопросам

четверг, 11 июля 2019 г.

Вывод знаковых и беззнаковых чисел в printf

Имеется следующий код:
#include
int main() { const unsigned char c1 = 200; const char c2 = -100; printf("sizeof(char)==%lu
", sizeof(char)); printf("%hhd %hhu
", c1, c1); printf("%hhd %hhu
", c2, c2); return 0; }
Его вывод:
sizeof(char)==1 200 200 -100 65436
Два вопроса:
Почему c1 в обоих случаях вывелось как 200, несмотря на то, что первый раз указывался спецификатор формата d (число со знаком)? Почему c2 во втором случае вывелось как 65436, ведь это выходит за пределы допустимого диапазона типа char, который в данном случае занимает один байт?
P.S. На всякий случай строка идентификации компилятора:
gcc (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 5.2.0


Ответ

Прежде всего хотел бы отметить, что показанный вами вывод на консоль не соответствует используемым спецификаторам формата в вызовах printf
Модификатор hh означает, что значение будет выводиться как значение объекта типа char. А это означает, что вы не можете получить значение 65436, так как объект типа char не может хранить такое значение в одном байте. Также для спецификатора формата вывода %hhd для значения 200 вы не можете получить то же самое значение, так как знаковые значения в объекте signed char не могут содержать значение 200. Это значение превышает максимально допустимое значение, равное 127.
200 200 -100 65436 ^^^^^
Я запустил ваш код на выполнение и получил следующий вывод на консоль
sizeof(char)==1 -56 200 -100 156 ^^^
Возможная причина, полученного вами результата состоит в том, что данные спецификаторы могут не поддерживаться той версией компилятора, которую вы используете, а потому вывод на консоль может быть неопределенным.
Теперь по поводу полученных мной значений.
Согласно стандарту C и описанию функции printf имеем, что
hh Specifies that a following d, i, o, u, x, or X conversion specifier applies to a signed char or unsigned char argument (the argument will have been promoted according to the integer promotions, but its value shall be converted to signed char or unsigned char before printing); or that a following n conversion specifier applies to a pointer to a signed char argument.
Следовательно, исходя из того, что вы объявили переменную c1 как
const unsigned char c1 = 200;
, то при целочисленном продвижении значения этой переменной до типа int внутреннее представление значения так и будет соответствовать значению 200. Поэтому, когда вы его выводите с помощью спецификатора формата %hhu, то будет выведено это же значение, то есть 200 Когда же вы его выводите с помощью спецификатора формата %hhd, то его внутреннее представление будет интерпретироваться как значение со знаком, а потому будет выведено -56. В сумме, если взять абсолютные значения этих двух чисел, то вы получите 256
То же самое имеет место для второй знаковой переменной c2, только ее значения будут равны, соответственно, -100 и 156 для %lld и %llu

Комментариев нет:

Отправить комментарий