88 votes

long long en C/C++

J'essaie ce code avec le compilateur C++ de GNU et je n'arrive pas à comprendre son comportement :

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

Lorsque je décompose la ligne commentée, le code ne compile pas et donne une erreur :

erreur : la constante entière est trop grande pour le type long

Mais si le code est compilé tel quel et exécuté, il produit des valeurs bien supérieures à 10000000000.

Pourquoi ?

9 votes

Il est peut-être trop tard maintenant, mais pour les futurs lecteurs, je vous suggère d'utiliser <stdint.h> et utiliser uint64_t . Pour afficher une valeur de 64 bits, printf( "%" PRIu64 "\n", val);

0 votes

@enthusiasticgeek <stdint.h> inclus, uint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );

0 votes

#define __STDC_FORMAT_MACROS 1 Voir stackoverflow.com/questions/14535556/

152voto

unwind Points 181987

Les lettres 100000000000 constituent une constante entière littérale, mais la valeur est trop grande pour le type int . Vous devez utiliser un suffixe pour modifier le type du littéral, c'est-à-dire

long long num3 = 100000000000LL;

Le suffixe LL transforme le littéral en type long long . C n'est pas assez "intelligent" pour conclure cela à partir du type à gauche, le type est une propriété du littéral lui-même, pas du contexte dans lequel il est utilisé.

49 votes

Lorsque cette réponse a été écrite, elle était probablement correcte, mais maintenant la norme C++ dit que le type d'un entier littéral sans suffixe est le premier de int , long int y long long int dans laquelle sa valeur peut être représentée. [C++ §2.14.2/2] Il n'est donc plus nécessaire d'ajouter le suffixe "LL" à un entier littéral qui est trop grand pour d'autres types.

8 votes

La raison pour laquelle ce problème se posait auparavant n'était pas que le C++ n'était pas assez "intelligent" pour déterminer le type littéral à partir du type de la variable à laquelle il était assigné, mais simplement que l'extension du compilateur n'implémentait pas le type entier étendu de manière à ce qu'il fonctionne bien avec le langage standard. Le C++ a désormais des règles qui font que tous les types d'entiers étendus s'intègrent mieux dans le langage standard : open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf

5 votes

@unwind Je pense que la réponse devrait être modifiée en fonction de ces suggestions.

28voto

Arkaitz Jimenez Points 10651

Essayez :

num3 = 100000000000LL;

Et BTW, en C++ il s'agit d'une extension du compilateur, le standard ne définit pas long long, cela fait partie de C99.

12 votes

Eh bien, le C++11 définit maintenant un long long

6voto

sellibitze Points 13607

Cela dépend du mode dans lequel vous compilez. long long ne fait pas partie de la norme C++ mais n'est (généralement) pris en charge qu'en tant qu'extension. Cela affecte le type de littéraux. Les entiers décimaux sans suffixe sont toujours de type int si l'int est suffisamment grand pour représenter le nombre, long sinon. Si le nombre est même trop grand pour long, le résultat est défini par l'implémentation (probablement un nombre de type long int tronqué pour des raisons de compatibilité ascendante). Dans ce cas, vous devez utiliser explicitement le suffixe LL pour activer l'extension long long (sur la plupart des compilateurs).

La prochaine version du C++ supportera officiellement long long de telle sorte que vous n'aurez plus besoin de suffixe à moins que vous ne vouliez explicitement forcer le type du littéral à être au moins long long. Si le nombre ne peut pas être représenté en long, le compilateur essaiera automatiquement d'utiliser long long même sans le suffixe LL. Je crois que c'est aussi le comportement de C99.

2voto

Omry Yadan Points 7523

Votre code se compile ici très bien (même avec cette ligne décommentée. j'ai dû la changer en

num3 = 100000000000000000000;

pour commencer à recevoir l'avertissement.

0 votes

Quel compilateur ? En C++, un entier littéral est le plus petit de int ou de long dans lequel il s'insère. En C99, c'est le plus petit de int, long, long long. Ainsi, lorsque vous ajoutez long long à C++ en tant qu'extension non standard, il se peut que votre compilateur ait également adopté les règles C99 pour les littéraux.

0 votes

Gcc version 4.3.2 (Debian 4.3.2-1.1) sur un système linux 64 bits.

0 votes

@SteveJessop Un peu tard peut-être : mais long n'est PAS nécessairement 64 bits. La plupart du temps, c'est le cas, mais vous n'avez aucune garantie que ce sera le cas partout. La seule garantie que vous avez est qu'il est au moins aussi grand qu'un int, qui à son tour est au moins aussi grand qu'un short int, qui à son tour est au moins aussi grand qu'un char. Enfin, char est défini comme étant suffisamment grand pour représenter tous les caractères de la chaîne de caractères de la mise en œuvre jeu de caractères de base (généralement 8 bits).

0voto

charlie Points 5

Remarque :

  1. supprimer le point-virgule après le fichier d'en-tête
  2. utiliser %lu au lieu de %u
  3. long long num3 = 100000000000LL ;

Remplacez ces éléments et vous serez prêt à partir :)

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