Estoy aprendiendo sobre la sobrecarga de funciones en C ++ y encontré esto:
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);
}
Por lo que entendí, cualquier valor dado en el int
rango (en mi caso int
es de 4 bytes) llamará display(int)
y cualquier valor fuera de este rango será ambiguo (ya que el compilador no puede decidir qué función llamar). Es válido para el rango completo de int
valores excepto su valor mínimo, es decir, -2147483648
cuando la compilación falla con el error
la llamada de sobrecargado
display(long int)
es ambigua
Pero tomar el mismo valor en an int
e imprimir el valor da 2147483648
. Estoy literalmente confundido con este comportamiento.
¿Por qué se observa este comportamiento solo cuando se pasa el número más negativo? (El comportamiento es el mismo si short
se usa a con -32768
- de hecho, en cualquier caso donde el número negativo y el número positivo tengan la misma representación binaria)
Compilador utilizado: g ++ (GCC) 4.8.5
fuente
call of overloaded ‘display(long int)’ is ambiguous
.typeof(-2147483648) != int
. El literal es2147483648
, que es demasiado grande para unint
, por lo que es unlong
, y está siendo negadoint j{-2147483648};
es una conversión estrecha. Casi vale la pena una pregunta en sí misma, eso. Probablemente esté relacionado con permitir (p. Ej.)long long
Valores constexpr, por ejemplo, que se reduzcan2147483647LL
en la inicialización.Respuestas:
Este es un error muy sutil. Lo que está viendo es una consecuencia de que no hay literales enteros negativos en C ++. Si miramos [lex.icon] obtenemos que un entero-literal ,
puede ser un decimal-literal ,
donde dígitos es
[0-9]
y distinto de cero dígitos es[1-9]
y el sufijo par puede ser uno deu
,U
,l
,L
,ll
, oLL
. En ninguna parte aquí se incluye-
como parte del literal decimal.En §2.13.2, también tenemos:
(énfasis mío)
Lo que significa que el
-
in-2147483648
es el unariooperator -
. Eso significa-2147483648
que en realidad se trata como-1 * (2147483648)
. Como2147483648
es demasiado para tiint
, se promueve along int
y la ambigüedad proviene de que no coincide.Si desea obtener el valor mínimo o máximo para un tipo de manera portátil, puede usar:
fuente
-2147483647 - 1
también funcionaría sin previo aviso como una expresión literal negativaINT_MIN
para la opción menos detallada. Aunque menos genérico.display(2147483649);
? ¿Por qué no puede llamar a la función int sin firmar en este caso? y ¿por qué trata el argumento2147483649
como int largo en lugar de int sin firmar?int
along int
along long int
. Nunca obtendrá un tipo sin signo para un literal decimal a menos que use el sufijou
/U
.display(unsigned a)
necesitadisplay(1234u);
odisplay(static_cast<unsigned>(1234));
ounsigned foo = 1234; display(foo);
La expresión en
-2147483648
realidad aplica el-
operador a la constante2147483648
. En su plataforma,int
no se puede almacenar2147483648
, debe estar representado por un tipo más grande. Por lo tanto,-2147483648
no se deduce que la expresión seasigned int
un tipo con signo más grande,signed long int
.Dado que no proporciona una sobrecarga,
long
el compilador se ve obligado a elegir entre dos sobrecargas que son igualmente válidas. Su compilador debería emitir un error de compilador sobre sobrecargas ambiguas.fuente
Ampliando las respuestas de los demás
Para aclarar por qué se confunde el OP, primero : considere la
signed int
representación binaria de2147483647
, a continuación.A continuación, agregue uno a este número : dando otro
signed int
de-2147483648
(que el OP desea usar)Finalmente: podemos ver por qué el OP se confunde cuando se
-2147483648
compila en a enlong int
lugar de asigned int
, ya que claramente cabe en 32 bits.Pero, como mencionan las respuestas actuales, el operador unario (
-
) se aplica después de resolver2147483648
cuál es along int
y NO cabe en 32 bits.fuente