J'apprends la surcharge de fonctions en C++ et je suis tombé sur ceci:
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);
}
D'après ce que j'ai compris, toute valeur donnée dans la plage int
(dans mon cas, int
est égale à 4 octets) appellera display(int)
et toute valeur en dehors de cette plage sera ambiguë (car le compilateur ne peut pas décider quelle fonction appeler). Il est valide pour la plage complète de int
valeurs, à l'exception de sa valeur minimale, à savoir -2147483648
, Où la compilation échoue avec l'erreur.
l'appel de surchargé
display(long int)
est ambigu
Mais en prenant la même valeur sur un int
et en imprimant la valeur, on obtient 2147483648
. Je suis littéralement confondu avec ce comportement.
Pourquoi ce comportement est observé uniquement lorsque le nombre le plus négatif est passé? (Le comportement est le même si un short
est utilisé avec -32768
- en fait, dans tous les cas où le nombre négatif et le nombre positif ont la même représentation binaire)
Compilateur utilisé: g ++ (GCC) 4.8.5
C'est une erreur très subtile. Ce que vous voyez est une conséquence de l'absence de littéraux entiers négatifs en C++. Si nous regardons [Lex.icon], nous obtenons qu’un entier-littéral ,
entier-littéral
suffixe entier littéral décimalopt
[...]
peut être un décimal-littéral ,
littéral décimal:
chiffre différent de zéro
decimal-literal ’ opt chiffre
où chiffre est [0-9]
et chiffre différent de zéro est [1-9]
Et le suffixe par peuvent être l'un de u
, U
, l
, L
, ll
, ou LL
. Nulle part ici n'inclut -
Comme faisant partie du littéral décimal.
Au §2.13.2, nous avons aussi:
Un littéral entier est une séquence de chiffres qui ne comporte aucune période ni partie d'exposant, avec une séparation facultative des guillemets simples qui sont ignorés lors de la détermination de sa valeur. Un littéral entier peut avoir un préfixe qui spécifie sa base et un suffixe qui spécifie son type. Le premier chiffre lexicalement de la séquence de chiffres est le plus significatif. A décimal le littéral entier (base dix) commence par un chiffre autre que 0 et consiste en une séquence de chiffres décimaux.
(c'est moi qui souligne)
Ce qui signifie que -
Dans -2147483648
Est le unaire operator -
. Cela signifie que -2147483648
Est en fait traité comme -1 * (2147483648)
. Puisque 2147483648
Est un de trop pour votre int
, il est promu en long int
Et l'ambiguïté vient de ce qui ne correspond pas.
Si vous souhaitez obtenir la valeur minimale ou maximale d'un type de manière portable, vous pouvez utiliser:
std::numeric_limits<type>::min(); // or max()
L'expression -2147483648
applique réellement le -
opérateur à la constante 2147483648
. Sur votre plate-forme, int
ne peut pas stocker 2147483648
, il doit être représenté par un type plus grand. Par conséquent, l'expression -2147483648
_ n'est pas déduit pour être signed int
mais un type plus gros signé, signed long int
.
Comme vous ne fournissez pas de surcharge pour long
, le compilateur est obligé de choisir entre deux surcharges ayant la même validité. Votre compilateur devrait générer une erreur de compilation à propos de surcharges ambiguës.
Développer les réponses des autres
Pour clarifier la raison pour laquelle le PO est confus, d’abord : considérons le signed int
représentation binaire de 2147483647
, au dessous de.
Ensuite, ajoutez un à ce nombre : donnant un autre signed int
de -2147483648
(que le PO souhaite utiliser)
Enfin: nous pouvons voir pourquoi le PO est confus quand -2147483648
compile en un long int
au lieu d'une signed int
, car il correspond clairement à 32 bits.
Mais, comme le mentionnent les réponses actuelles, l'opérateur unaire (-
) est appliqué après résolvant 2147483648
qui est un long int
et ne correspond PAS à 32 bits.