Ответ 1
Это не Undefined Поведение, это просто потрясающее изменение в стандарте языка C между C89 и C99.
В C89 целочисленные константы, такие как 4008636143, которые не помещаются в int
или long int
, но вписываются в unsigned int
, не имеют знака, но на C99 они либо long int
, либо long long int
( в зависимости от того, какой из них является наименьшим, который может удерживать значение). В результате все выражения оцениваются с использованием 64 бит, что приводит к неправильному ответу.
Visual Studio является компилятором C89 и поэтому приводит к поведению C89, но эта ссылка Ideone компилируется в режиме C99.
Это становится более очевидным, если вы скомпилируете GCC с помощью -Wall
:
test.c: In function ‘divisible15’:
test.c:8:3: warning: this decimal constant is unsigned only in ISO C90
Из C89 §3.1.3.2:
Тип целочисленной константы является первым из соответствующих список, в котором может быть представлено его значение. Unsuffixed decimal: int, long int, unsigned long int; unsuffixed восьмеричный или шестнадцатеричный: int, unsigned int, long int, unsigned long int; [...]
C99 §6.4.4.1/5-6:
5) Тип целочисленной константы является первым из соответствующего списка, в котором его значение может быть представленным.
Suffix | Decimal Constant | Octal or Hexadecimal Constant -------+------------------+------------------------------ none | int | int | long int | unsigned int | long long int | long int | | unsigned long int | | long long int | | unsigned long long int -------+------------------+------------------------------ [...]
6) Если целочисленная константа не может быть представлена каким-либо типом в ее списке, она может иметь расширенный целочисленный тип, если расширенный целочисленный тип может представлять его значение. Если все типы в списке для константы подписаны, расширенный целочисленный тип должен быть подписан. [...]
Для полноты, С++ 03 действительно имеет Undefined Поведение, когда целочисленная константа слишком велика, чтобы соответствовать в long int
. Из С++ 03 §2.13.1/2:
Тип целочисленного литерала зависит от его формы, значения и суффикса. Если он десятичен и не имеет суффикса, он имеет первый из этих типов, в котором может быть представлено его значение:
int
,long int
; если значение не может быть представлено какlong int
, поведение undefined. Если он восьмеричный или шестнадцатеричный и не имеет суффикса, он имеет первый из этих типов, в котором может быть представлено его значение:int
,unsigned int
,long int
,unsigned long int
. [...]
Поведение С++ 11 идентично C99, см. С++ 11 §2.14.2/3.
Чтобы гарантировать постоянство поведения кода при компиляции как C89, C99, С++ 03 и С++ 11, простое исправление состоит в том, чтобы сделать константу 4008636143 неподписанной, суффиктируя ее с помощью u
как 4008636143u
.