Estou aprendendo sobre sobrecarga de função em C ++ e me deparei com o seguinte:
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);
}
Pelo que entendi, qualquer valor dado no int
intervalo (no meu caso int
é 4 bytes) será chamado display(int)
e qualquer valor fora desse intervalo será ambíguo (já que o compilador não pode decidir qual função chamar). É válido para toda a gama de int
valores excepto o seu valor mínimo, isto é, -2147483648
onde a compilação falha com o erro
chamada de sobrecarregado
display(long int)
é ambígua
Mas pegar o mesmo valor para um int
e imprimir o valor dá 2147483648
. Estou literalmente confuso com esse comportamento.
Por que esse comportamento é observado apenas quando o número mais negativo é passado? (O comportamento é o mesmo se a short
for usado com -32768
- de fato, em qualquer caso onde o número negativo e o número positivo têm a mesma representação binária)
Compilador usado: g ++ (GCC) 4.8.5
fonte
call of overloaded ‘display(long int)’ is ambiguous
.typeof(-2147483648) != int
. O literal é2147483648
, que é muito grande para umint
, então é umlong
, e está sendo negadoint j{-2147483648};
é uma conversão de estreitamento. Quase vale a pena uma pergunta, isso. Provavelmente está relacionado a permitir (por exemplo)long long
valores constexpr como2147483647LL
estreitos na inicialização.Respostas:
Este é um erro muito sutil. O que você está vendo é uma consequência de não haver literais inteiros negativos em C ++. Se olharmos para [lex.icon], obtemos um literal inteiro ,
pode ser um literal decimal ,
onde dígitos é
[0-9]
e diferente de zero dígitos é[1-9]
e o sufixo nominal pode ser uma deu
,U
,l
,L
,ll
, ouLL
. Em nenhum lugar aqui ele inclui-
como parte do literal decimal.Em §2.13.2, também temos:
(ênfase minha)
O que significa que o
-
in-2147483648
é unáriooperator -
. Isso significa que-2147483648
é realmente tratado como-1 * (2147483648)
. Como2147483648
é demais para você,int
ele é promovidolong int
a ae a ambigüidade vem dessa não correspondência.Se você deseja obter o valor mínimo ou máximo para um tipo de maneira portátil, pode usar:
fonte
-2147483647 - 1
também funcionaria sem aviso como uma expressão literal negativaINT_MIN
para a opção menos detalhada. Menos genérico, porém.display(2147483649);
. Por que ele não pode chamar a função int sem sinal neste caso? e por que ele trata o arg2147483649
como long int em vez de unsigned int?int
along int
paralong long int
. Você nunca obterá um tipo sem sinal para um literal decimal, a menos que use o sufixou
/U
.display(unsigned a)
você precisa dedisplay(1234u);
oudisplay(static_cast<unsigned>(1234));
ouunsigned foo = 1234; display(foo);
A expressão
-2147483648
está, na verdade, aplicando o-
operador à constante2147483648
. Na sua plataforma,int
não pode armazenar2147483648
, deve ser representado por um tipo maior. Portanto, a expressão-2147483648
não é deduzida como sendosigned int
um tipo maior com sinalsigned long int
,.Como você não fornece uma sobrecarga para
long
o compilador, ele é forçado a escolher entre duas sobrecargas que são igualmente válidas. Seu compilador deve emitir um erro do compilador sobre sobrecargas ambíguas.fonte
Expandindo as respostas dos outros
Para esclarecer porque o OP é confuso, primeiro : considere a
signed int
representação binária de2147483647
, abaixo.Em seguida, adicione um a este número : dando outro
signed int
de-2147483648
(que o OP deseja usar)Finalmente: podemos ver porque o OP fica confuso quando
-2147483648
compila para um emlong int
vez de umsigned int
, já que ele claramente se encaixa em 32 bits.Mas, como as respostas atuais mencionam, o operador unário (
-
) é aplicado após a resolução2147483648
que é along int
e NÃO cabe em 32 bits.fonte