Непреднамеренный неподписанный максимальный результат

Я пытаюсь выполнить упражнение 2-1 из K&R C, но когда я запускаю программу, результат такой:

        UNSIGNED TYPES
UNSIGNED CHAR:  0     255
UNSIGNED SHORT: 0     65535
UNSIGNED INT:   0     -1
UNSIGNED LONG;  0     -1

Результат UNSIGNED INT и UNSIGNED LONG не должен был быть -1, он должен был быть значением в ссылке. (Приложение B.11, стр. 213)

/* UNSIGNED TYPES */
printf("\n\tUNSIGNED TYPES\n");
printf("UNSIGNED CHAR:  %d      %d\n", 0, UCHAR_MAX);
printf("UNSIGNED SHORT: %d      %d\n", 0, USHRT_MAX);
printf("UNSIGNED INT:   %d      %d\n", 0, UINT_MAX);
printf("UNSIGNED LONG:  %d      %d\n", 0, ULONG_MAX);

Странно то, что я не думаю, что с моим кодом что-то не так, минимальный диапазон равен 0, потому что я читал, что unsigned типы неотрицательны. Я уже включил limits.h и float.h.

Как решить эту проблему?

Ссылка на полную программу находится здесь.

ОБНОВЛЕНИЕ 1: я попытался заменить %d максимального диапазона на unsigned long, и это, похоже, сработало, но unsigned int стало 4294967925 вместо 65535. Спасибо, что помогли мне решить проблему unsigned long, и я надеюсь, что вы, ребята, поможете мне с проблемой unsigned int.

ОБНОВЛЕНИЕ 2: я изменил последовательность символов ULONG_MAX с %ul на %lu.

Вот код и результат:

Код:

/* UNSIGNED TYPES */
printf("\n\tUNSIGNED TYPES\n");
printf("UNSIGNED CHAR:  %d      %u\n", 0, UCHAR_MAX);
printf("UNSIGNED SHORT: %d      %u\n", 0, USHRT_MAX);
printf("UNSIGNED INT:   %d      %u\n", 0, UINT_MAX);
printf("UNSIGNED LONG:  %d      %lu\n", 0, ULONG_MAX);

Результат:

        UNSIGNED TYPES
UNSIGNED CHAR:  0     255
UNSIGNED SHORT: 0     65535
UNSIGNED INT:   0     4294967925
UNSIGNED LONG;  0     4294967925

person Alexander B. Falgui    schedule 26.05.2014    source источник
comment
%ul должно быть %lu, и вы неправильно расшифровали l как 1 в последней строке результата.   -  person M.M    schedule 26.05.2014
comment
Я уже сделал это, и, похоже, это работает намного лучше, чем %ul, но не могли бы вы объяснить (если знаете), почему %ul добавляет единицу в конце ULONG_MAX? а почему %lu нет?   -  person Alexander B. Falgui    schedule 26.05.2014
comment
%ul это %u, за которым следует буква l.   -  person M.M    schedule 26.05.2014


Ответы (3)


%d для целых чисел со знаком, для unsigned int и long используйте %u и %lu соответственно.

person Rohan    schedule 26.05.2014
comment
Это сработало для unsigned long (ULONG_MAX), но разве UINT_MAX не должно быть 65535 вместо 4294967925? - person Alexander B. Falgui; 26.05.2014
comment
Я не думаю, что %ul - это POSIX. Вместо этого вы должны использовать %lu. - person Potatoswatter; 26.05.2014
comment
@Potatoswatter Хорошо, это сделало ULONG_MAX лучше, но как насчет UINT_MAX? - person Alexander B. Falgui; 26.05.2014
comment
@AlexanderB.Falgui Для этого вам просто нужен простой %u. - person Potatoswatter; 26.05.2014
comment
@AlexanderB.Falgui, на 64-битных машинах int также имеет длину 4 байта. - person Rohan; 26.05.2014
comment
@Potatoswatter, как мне заставить работать %ju? макрос PRIuMAX из <inttypes.h> печатает 4924261 вместо 65535... - person Alexander B. Falgui; 26.05.2014
comment
@AlexanderB.Falgui Извините, я неправильно понял вопрос. %ju полностью относится к другому типу, uintmax_t обычно это unsigned long long. Комментарий отредактирован; вам нужен только простой %u. - person Potatoswatter; 26.05.2014

Вам нужно использовать спецификацию формата %u для печати беззнакового целого числа.

При использовании %d битовый шаблон интерпретируется как целое число со знаком.

person ooga    schedule 26.05.2014

Вы точно скопировали вывод программы? Вы пишете UNSIGNED LONG: в коде, а на выходе получается UNSIGNED LONG;. unsigned long не может быть на одну цифру длиннее, чем unsigned int

Кроме того, вы используете неверный спецификатор типа, что приводит к неопределенному поведению. Вы должны использовать %u для unsigned int, с модификатором длины l для long, ll для long long.

Эпоха 16-битных вычислений давно миновала несколько десятилетий назад, поэтому размер int составляет 32 бита в большинстве современных систем, за исключением некоторых 8- или 16-битных встроенных систем, следовательно, диапазон составляет [0, 232- 1] или [0, 4294967295], как видите. В зависимости от используемых вами систем long будет иметь разные размеры. Обычно в Windows это 32-битный тип, а в Unix/Linux — 64-битный. Стандарт C требует, чтобы int было не менее 16 бит, long - не менее 32 бит. Только long long гарантированно будут не менее 64 бит, поэтому вам также нужно проверить это.

printf("UNSIGNED CHAR:       %u    %u\n",   0U, UCHAR_MAX);
printf("UNSIGNED SHORT:      %u    %u\n",   0U, USHORT_MAX);
printf("UNSIGNED INT:        %u    %u\n",   0U, UINT_MAX);
printf("UNSIGNED LONG:       %lu   %lu\n",  0UL, ULONG_MAX);
printf("UNSIGNED LONG LONG:  %llu  %llu\n", 0ULL, ULONGLONG_MAX);

Если вы работаете в Windows, максимальное значение для unsigned int и unsigned long должно быть 4294967295.

Обратите внимание, что использование ВСЕХ ЗАГЛАВНЫХ букв — очень плохой выбор.

person phuclv    schedule 26.05.2014
comment
Я бы добавил +1 к вашему ответу, так как он дал мне больше информации о 16, 32 и 64 битах, но мне не хватает репутации для этого. Я сделаю это, если смогу. - person Alexander B. Falgui; 26.05.2014