Пример 2.1, K&R: неверное значение символической константы для LONG_MIN и LONG_MAX?

Это код, который я использую для поиска значений символических констант для LONG.

   #include <limits.h>     //These header files contains the symbolic constants
   #include <float.h>      //for different datatypes

   #include <stdio.h>

    int main(void){

            printf("\tMininum numeric value for long type: %ld\n", LONG_MIN);
            printf("\tMaximum numeric value for long type: %ld\n", LONG_MAX);

            printf("\tMaximum numeric value for unsigned long type: %lu\n", (unsigned)ULONG_MAX);
    return 0;
   }  

Результат, который я получаю:

  Mininum numeric value for long type: -9223372036854775808
  Maximum numeric value for long type: 9223372036854775807
  Maximum numeric value for unsigned long type: 4294967295

Но если посмотреть limit.h на странице руководства. Это символические константы для LONG_MIN, LONG_MAX, LLONG_MIN и LLONG_MAX из файла limits.h в моей системе.

  {LONG_MIN}
          Minimum value of type long.
          Maximum Acceptable Value: -2 147 483 647

  {LONG_MAX}
          Maximum value of a long.
          Minimum Acceptable Value: +2 147 483 647

  {LLONG_MIN}
          Minimum value of type long long.
          Maximum Acceptable Value: -9223372036854775807

  {LLONG_MAX}
          Maximum value of type long long.
          Minimum Acceptable Value: +9223372036854775807

Как будто программа выдает мне значения из Long long символических констант.

Почему это происходит?


person hsuyaa    schedule 22.06.2016    source источник
comment
Вы переводите ULONG_MAX в unsigned, что недостаточно велико для хранения значения (в вашей системе). Приведение не требуется.   -  person davmac    schedule 22.06.2016
comment
Извините, почему вы помечаете этот вопрос как c++, когда цитируете примеры K&R? Пожалуйста, не путайте языки. Уберите отсюда тег c++, пожалуйста.   -  person Luis Colorado    schedule 23.06.2016


Ответы (3)


Размер типов является переменным. long составляет минимум 32 бита (что дает диапазон +-2 миллиарда), но может быть больше. В 64-битной системе это может быть, например, 64-бит.

long long должно быть не менее 64 бит, но, конечно, может быть и больше.

Эти размеры зависят от базовой аппаратной платформы и компилятора. Например, в 64-разрядной системе Windows с использованием GCC long составляет 64 бита, но при использовании компилятора Visual C++ long составляет «всего» 32 бита.

Подробнее о целочисленных типах читайте в этом справочнике.

person Some programmer dude    schedule 22.06.2016
comment
Хорошо, но тогда почему я получаю 32-битное значение для unsigned long? - person hsuyaa; 22.06.2016
comment
@hsuyaa Потому что вы привели его к unsigned int (unsigned — это сокращение от unsigned int, потому что int — целочисленный тип по умолчанию), который обычно составляет 32 бита. Если вы хотите unsigned long, вы должны использовать его как таковой. - person Some programmer dude; 22.06.2016
comment
Спасибо! Можем ли мы привести результат к unsigned long? - person hsuyaa; 22.06.2016
comment
@hsuyaa Да, ты должен. - person Some programmer dude; 22.06.2016
comment
@hsuyaa, вы также используете %lu для печати unsigned вместо %u, так что можно только догадываться, что произойдет. Я рекомендую предупреждения компилятора. - person chris; 22.06.2016

Очевидно, что long в вашей системе 64-битный.

Стандарт C определяет минимальные ограничения для целочисленных типов. Это означает, что, например, LONG_MAX должно быть не менее 2 147 483 647, но может быть и больше.

Кстати, это ошибка: (unsigned)ULONG_MAX. Должно быть unsigned long.


Одно интересное любопытство: обратите внимание, например, что LONG_MIN должно быть не менее -2 147 483 647. Но даже в обычной 32-битной системе с дополнением до двух оно никогда не имеет такого значения!
Оно имеет значение -2 147 483 648. Это сделано намеренно, чтобы разрешить систему дополнений и знаков и величин.

person Lundin    schedule 22.06.2016
comment
Также любопытно, что в MSVC есть #define LONG_MIN (-2147483647L - 1), который делается таким образом, чтобы компилятор не жаловался на то, что 2147483648L находится вне диапазона (до отрицания). - person Weather Vane; 22.06.2016
comment
@WeatherVane Ну, я думаю, это еще один недостаток дизайна в C ... отрицательных литералов не существует до того, как вы примените к ним унарный оператор минус. - person Lundin; 22.06.2016

Это то, что он говорит.

Minimum Acceptable Value: +2 147 483 647

"Минимально приемлемое значение" для LONG_MAX таково. Ваше значение для LONG_MAX (поскольку ваша система 64-разрядная) выше.

Так что нет проблем.

person Lightness Races in Orbit    schedule 22.06.2016