Вопрос о типе данных C и константе - PullRequest
2 голосов
/ 22 марта 2011

Привет!Я экспериментировал с языком Си, пока не столкнулся с чем-то очень странным.Я не смог объяснить себе результат, показанный ниже.

Код:

#include <stdio.h>

int main(void)
{
    int num = 4294967295U;
    printf("%u\n", num);
    return 0;
}

Вопрос:

1.) Как видите, я создал int, который может содержать числа от -2147483648 до 2147483647 .

2.) Когда я присваиваю значение 4294967295 к этой переменной в среде IDE отображается предупреждение во время компиляции из-за переполнения переменной.

3.) Из-за любопытства я добавил U (без знака) за номером и когда я перекомпилировал его, компилятор не возвратил никакого предупреждающего сообщения.

4. Я провел дополнительные эксперименты, изменив U (без знака) на L (long) и LL (long long) .Как и ожидалось, предупреждающее сообщение все еще сохраняется для этих двух, но не после того, как я изменил его на UL (без знака Long) и ULL (без знака Long Long) .

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

Предупреждающее сообщение: (для шагов 2)

warning #2073: Overflow in converting constant expression from 'long long int' to 'int'.

Предупреждающее сообщение: (Для шагов 4 LL & L )

warning #2073: Overflow in converting constant expression from 'long long int' to 'long int'.

И наконец, спасибо за чтение моего вопроса, ваши учения и советы очень ценятся.

Ответы [ 2 ]

6 голосов
/ 22 марта 2011

Согласно стандарту ISO C99, раздел 6.4.4.1 ( Целочисленные константы ), подраздел Семантика , тип целочисленной константы является первым типом следующей таблицы, где значение может быть представлено:

                                    Octal or Hexadecimal
Suffix            Decimal Constant            Constant
none         int                    int
             long int               unsigned int
             long long int          long int
                                    unsigned long int
                                    long long int
                                    unsigned long long int

u or U       unsigned int           unsigned int
             unsigned long int      unsigned long int
             unsigned long long int unsigned long long int

l or L       long int               long int
             long long int          unsigned long int
                                    long long int
                                    unsigned long long int

both u or U  unsigned long int      unsigned long int
and l or L   unsigned long long int unsigned long long int

ll or LL     long long int          long long int
                                    unsigned long long int

both u or U  unsigned long long int unsigned long long int
and ll or LL

Отдельные реализации могут иметь расширенные целочисленные типы, которые следуют той же схеме, что и выше.

4 голосов
/ 22 марта 2011

Возможно, по умолчанию компилятор предполагает, что вы вводите целые числа со знаком. Когда вы даете ему 4294967295, это число не помещается в 4-байтовое целое число, поэтому вместо него используется 8-байтовое целое число. Затем он должен выполнить преобразование с потерями (long long, 8-байтовый AKA, в long, 4-байтовый AKA), поэтому он выдает предупреждение.

Однако, когда вы набираете 4294967295U, он знает, что вам нужно целое число без знака. Это число вписывается в 4-байтовое целое число без знака, поэтому оно имеет тип long int, и преобразование с потерями не требуется. (Вы не теряете данные, переходя от unsigned long int к long int, просто неправильно представляете их.)

...