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 int
plage (dans mon cas int
est de 4 octets) sera appelée display(int)
et toute valeur en dehors de cette plage sera ambiguë (puisque le compilateur ne peut pas décider quelle fonction appeler). Il est valide pour toute la plage de int
valeurs sauf sa valeur minimale, c'est-à-dire -2147483648
lorsque la compilation échoue avec l'erreur
l'appel de surcharge
display(long int)
est ambigu
Mais prendre la même valeur à un int
et imprimer la valeur donne 2147483648
. Je suis littéralement confus avec ce comportement.
Pourquoi ce comportement n'est-il observé que lorsque le nombre le plus négatif est passé? (Le comportement est le même si a 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
la source
call of overloaded ‘display(long int)’ is ambiguous
.typeof(-2147483648) != int
. Le littéral est2147483648
, qui est trop grand pour unint
, donc c'est unlong
, et il est annuléint j{-2147483648};
une conversion restrictive. Cela vaut presque une question en soi. C'est probablement lié au fait d'autoriser (par exemple) leslong long
valeurs constexpr telles que2147483647LL
d'être réduites lors de l'initialisation.Réponses:
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 un entier-littéral ,
peut être un littéral décimal ,
où chiffre est
[0-9]
et chiffres d' une valeur non nulle est[1-9]
et par suffixe peut être l' unu
,U
,l
,L
,ll
, ouLL
. Nulle part ici cela ne fait-
partie du littéral décimal.Au §2.13.2, nous avons également:
(c'est moi qui souligne)
Ce qui signifie que le
-
in-2147483648
est unaireoperator -
. Cela signifie-2147483648
est réellement traité comme-1 * (2147483648)
. Puisqu'il2147483648
y en a un de trop pour votre,int
il est promu à unlong 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:
la source
-2147483647 - 1
fonctionnerait également sans avertissement comme une expression littérale négativeINT_MIN
pour l'option la moins verbeuse. Moins générique, cependant.display(2147483649);
. Pourquoi ne peut-il pas appeler la fonction int unsigned dans ce cas? et pourquoi il traite l'argument2147483649
comme long int au lieu de unsigned int?int
àlong int
àlong long int
. Vous n'obtiendrez jamais un type non signé pour un littéral décimal sauf si vous utilisez le suffixeu
/U
.display(unsigned a)
vous avez besoin dedisplay(1234u);
oudisplay(static_cast<unsigned>(1234));
ouunsigned foo = 1234; display(foo);
L'expression
-2147483648
applique en fait l'-
opérateur à la constante2147483648
. Sur votre plateforme,int
impossible de stocker2147483648
, il doit être représenté par un type plus grand. Par conséquent, l'expression-2147483648
ne se déduit pas être ,signed int
mais un type plus grand signé,signed long int
.Puisque vous ne fournissez pas de surcharge,
long
le compilateur est obligé de choisir entre deux surcharges qui sont toutes deux également valides. Votre compilateur doit émettre une erreur de compilation concernant les surcharges ambiguës.la source
Élargir les réponses des autres
Pour clarifier pourquoi l'OP est confus, tout d'abord : considérez la
signed int
représentation binaire de2147483647
ci-dessous.Ensuite, ajoutez un à ce numéro : en donnant un autre
signed int
de-2147483648
(que l'OP souhaite utiliser)Enfin: nous pouvons voir pourquoi l'OP est confus lors de la
-2147483648
compilation en a aulong int
lieu de asigned int
, car il tient clairement en 32 bits.Mais, comme le mentionnent les réponses actuelles, l'opérateur unaire (
-
) est appliqué après la résolution de2147483648
ce qui est along int
et ne tient PAS dans 32 bits.la source