Я изучаю перегрузку функций в C ++ и наткнулся на это:
void display(int a)
{
cout << "int" << endl;
}
void display(unsigned a)
{
cout << "unsigned" << endl;
}
int main()
{
int i = -2147483648;
cout << i << endl; //will display -2147483648
display(-2147483648);
}
Насколько я понял, любое значение, указанное в int
диапазоне (в моем случае int
- 4 байта), будет вызывать, display(int)
и любое значение за пределами этого диапазона будет неоднозначным (поскольку компилятор не может решить, какую функцию вызвать). Он действителен для всего диапазона int
значений, кроме его минимального значения, т.е. -2147483648
когда компиляция завершается с ошибкой.
вызов перегруженного
display(long int)
неоднозначен
Но если взять одно и то же значение для an int
и распечатать его, получится 2147483648
. Меня буквально смущает такое поведение.
Почему такое поведение наблюдается только тогда, когда передается самое отрицательное число? (Поведение такое же, если short
используется с -32768
- фактически, в любом случае, когда отрицательное число и положительное число имеют одинаковое двоичное представление)
Используемый компилятор: g ++ (GCC) 4.8.5
источник
call of overloaded ‘display(long int)’ is ambiguous
.typeof(-2147483648) != int
. Буквальное значение2147483648
слишком велико для aint
, поэтому оноlong
отрицаетсяint j{-2147483648};
это сужающее преобразование. Это почти само по себе вопрос. Вероятно, это связано с разрешением (например)long long
сужения значений constexpr2147483647LL
при инициализации.Ответы:
Это очень тонкая ошибка. То, что вы видите, является следствием отсутствия отрицательных целочисленных литералов в C ++. Если мы посмотрим на [lex.icon], мы получим целочисленный литерал ,
может быть десятичным-буквальным ,
где цифра является
[0-9]
и отличной от нуля цифра является[1-9]
и суффикс пар может быть один изu
,U
,l
,L
,ll
, илиLL
. Здесь он не-
является частью десятичного литерала.В п. 2.13.2 мы также имеем:
(курсив мой)
Это означает, что
-
in-2147483648
является унарнымoperator -
. Это означает,-2147483648
что фактически рассматривается как-1 * (2147483648)
. Так как2147483648
это слишком много для вас,int
он повышается до a,long int
и неоднозначность возникает из-за несоответствия.Если вы хотите получить минимальное или максимальное значение для типа переносимым способом, вы можете использовать:
std::numeric_limits<type>::min(); // or max()
источник
-2147483647 - 1
также будет работать без предупреждения как отрицательное буквальное выражениеINT_MIN
для наименее подробного варианта. Хотя менее общий.display(2147483649);
. Почему в этом случае нельзя вызвать функцию unsigned int? и почему он обрабатывает arg2147483649
как long int вместо unsigned int?int
доlong int
доlong long int
. Вы никогда не получите беззнаковый тип для десятичного литерала, если не используете суффиксu
/U
.display(unsigned a)
, нужно либоdisplay(1234u);
или,display(static_cast<unsigned>(1234));
либоunsigned foo = 1234; display(foo);
Выражение
-2147483648
фактически применяет-
оператор к константе2147483648
. На вашей платформеint
нельзя хранить2147483648
, он должен быть представлен более крупным шрифтом. Следовательно, выражение-2147483648
не выводится какsigned int
более крупный знаковый типsigned long int
.Поскольку вы не предоставляете перегрузку,
long
компилятор вынужден выбирать между двумя перегрузками, которые одинаково допустимы. Ваш компилятор должен выдать ошибку компилятора о неоднозначных перегрузках.источник
Расширение ответов на другие вопросы
Чтобы прояснить, почему путают OP, сначала : рассмотрите
signed int
двоичное представление2147483647
ниже.Затем добавьте один к этому числу : предоставив другой
signed int
из-2147483648
(который OP желает использовать)Наконец: мы можем понять, почему OP сбивается с толку при
-2147483648
компиляции в along int
вместо asigned int
, поскольку он явно умещается в 32 бита.Но, как упоминается в текущих ответах, унарный оператор (
-
) применяется после разрешения,2147483648
которое является along int
и НЕ подходит для 32 бит.источник