У меня есть следующий код:
UINT64 time1 = 215510*10000;
UINT64 time2 = (UINT64)(215510 * 10000);
При печати или в режиме "Watch" получается:
time1 = 18446744071569684320
time2 = 18446744071569684320
На самом деле я знаю, как сделать это прямо здесь. Для получения правильного ответа мы должны использовать один из следующих кодов (следующие 3 версии все в порядке):
UINT64 time3 = (UINT64)215510 * 10000;
UINT64 time4 = 215510 * (UINT64)10000;
UINT64 time5 = (UINT64)215510 * (UINT64)10000;
Но почему первые две строки не могут дать правильный ответ?
Поскольку литеральная константа, как 215510
, как правило, int
(не long
) в стандарте C++. Он не связан с Visual Studio (он должен быть таким же с другим компилятором, как GCC, ака g++
по крайней мере, если int
имеет 32 бита), поэтому 215510 * 10000
также является int
. Попробуйте 215510L * 10000
чтобы иметь один множитель и быть long
(следовательно, продукт также будет long
- это не изменит продукт, если он еще long
32 бита!) Или даже 215510LL
чтобы сделать его long long
или с явным литом (int64_t)215510
...
И на вашей платформе int
, вероятно, 32 бита. Таким образом, подписанный INT_MAX
составляет 2147483647
(что составляет 2 31 - 1).
И Кейт Томпсон справедливо прокомментировал это
Тип целочисленной константы является первым из соответствующего списка, в котором может быть представлено его значение.
per (стандарт C11 §6.4.4.1, пункт 5 или) C++ 11 стандарт §2.14.2, пункт 2. Таким образом, реализация с 16 битами int
и long
32 бит 215510
является long
константой литерала (поскольку 215510> 32767, которая будет его INT_MAX
....).
Так что, вопреки тому, что я считаю, тип литеральной интегральной константы не определяется суффиксом -or недостатком it-, но и его значением!
215510
имеет тип int
только в том случае, если int
достаточно велик для его хранения. int
может быть как 16 битов, что делает INT_MAX
32767; в такой системе 215510
будет иметь тип long
.
long
также имеет 32 бита, этот ответ не будет полезен. И согласно документации , это так.
Это связано с тем, что вы вызываете переполнение целых чисел путем умножения двух 32-разрядных чисел, результат которых превышает 32 бита. Сначала вам нужно преобразовать в 64 бита, как вы уже показали.
В C++ недопустимый целочисленный литерал имеет тип int
, long int
или long long int
, в зависимости от того, какой из них является первым, в котором может быть представлено его значение. (long long int
был относительно недавним дополнением к языку).
Вероятно, в вашей системе 215510
и 10000
имеют тип int
, который, вероятно, является 32-битным типом.
Выражения (обычно) оцениваются сами по себе, независимо от контекста, в котором они появляются. Таким образом, выражение 215510*10000
оценивается как int
. Поскольку математический результат превышает INT_MAX
, результат не определен, но он, вероятно, будет -2139867296
.
Когда это значение преобразуется в 64-разрядный неподписанный тип, он обтекает, получая 18446744071569684320
(что немного меньше 2 64).
215510
всегда является int
(это не система конкретным, требуются по стандарту).
int
, long int
; если значение не может быть представлено как long int
, поведение не определено. " Стандарт 2011 добавляет long long int
и показывает правила в таблице.
215510*10000
- этоint
потому что оба операнда являютсяint
.