91 votes

Pourquoi la valeur int la plus négative provoque-t-elle une erreur concernant les surcharges de fonctions ambiguës?

Je suis en apprentissage à propos de la surcharge de fonctions en C++ et 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);
}

De ce que j'ai compris, toute valeur donnée dans l' int de la gamme (dans mon cas int est de 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 valable pour la gamme complète des int valeurs à l'exception de sa valeur min c'est à dire -2147483648 où la compilation échoue avec l'erreur

appel de surchargés display(long int) est ambigu

Mais en prenant la même valeur à un int et l'impression de la valeur donne 2147483648. Je suis littéralement confondre avec ce comportement.

Pourquoi est-ce le comportement observé que lorsque la plupart d'un nombre négatif est-il 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 positif nombre ont la même représentation binaire)

Compilateur utilisé: g++ (GCC) 4.8.5

145voto

NathanOliver Points 10062

C'est un très subtile erreur. Ce que vous voyez est une conséquence il n'y a pas négatif les littéraux entiers en C++. Si l'on regarde [lex.icône] on obtient un entier littéral,

entier littéral
        virgule-littéral entier-le suffixeopt
[...]

peut être une virgule littérale,

virgule-littérale:
        différent de zéro chiffres
        virgule-littérale ' opt chiffres

où le chiffre est - [0-9] et différente de zéro chiffres est - [1-9] et le suffixe normale peut être l'une des u, U, l, L, llou LL. Nulle part ici ne comprennent - comme faisant partie de la décimale littérale.

Dans le §2.13.2, nous avons aussi:

Un littéral entier est une séquence de chiffres qui n'a pas de période ou de l'exposant de la partie, avec en option la séparation 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 indique sa base et d'un suffixe qui indique son type. Le lexicalement premier chiffre de la séquence de chiffres est la plus importante. Un décimal entier littéral (base dix) commence par un chiffre autre que 0 et se compose d'une séquence de chiffres décimaux.

(l'emphase est mienne)

Ce qui signifie que l' - en -2147483648 est unaire operator -. Cela signifie que -2147483648 est effectivement traitée comme -1 * (2147483648). Depuis 2147483648 c'est un de trop pour votre int il est promu à un long int et l'ambiguïté provient de la non correspondance.

Si vous souhaitez obtenir la valeur minimale ou maximale pour un type dans une manière portable, vous pouvez utiliser:

std::numeric_limits<type>::min();  // or max()

36voto

François Andrieux Points 16034

L'expression -2147483648 est en fait l'application de l' - de l'opérateur de la constante 2147483648. Sur votre plate-forme, int ne peuvent pas stocker 2147483648, il doit être représenté par un plus grand type. Par conséquent, l'expression -2147483648 n'est pas déduites à signed int , mais un plus grand type signé, signed long int.

Puisque vous ne fournissez pas une surcharge pour l' long le compilateur est forcé de choisir entre deux surcharges qui sont à la fois tout aussi valable. Votre compilateur doit émettre une erreur de compilation sur ambiguë surcharges.

4voto

Jesse Salazar Points 317

Étendre sur les réponses des autres


Pour clarifier les raisons de l'OP est confus, d'abord: prendre en compte les signed int représentation binaire de l' 2147483647, ci-dessous.

Largest signed int




Ensuite, ajoutez-en une de ce numéro: donner un autre signed int de -2147483648 (que l'OP veut utiliser). Smallest signed int



Enfin: on peut voir pourquoi l'OP est confus lorsqu' -2147483648 compile à un long int au lieu de signed int, car il s'inscrit en 32 bits.

Mais, en tant que réponses mentionner, l'opérateur unaire (-) est appliqué après la résolution de 2147483648 qui est un long int et ne rentre PAS en 32 bits.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X