Comment formater un entier long long non signé en utilisant printf?

379
#include <stdio.h>
int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %ul. A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Production:

My number is 8 bytes wide and its value is 285212672l. A normal number is 0.

Je suppose que ce résultat inattendu provient de l'impression du unsigned long long int. Comment avez - vous printf()une unsigned long long int?

andrewrk
la source
2
Je viens de compiler votre code (avec% llu) avec gcc et la sortie était la bonne. Transmettez-vous des options au compilateur?
Juan
2
Notez que newlib de samsung bada ne semble pas prendre en charge "% lld": developer.bada.com/forum/…
RzR
Je suggérerais d'utiliser stdint.h et d'être explicite sur le nombre de bits de votre variable. Nous sommes toujours dans une période de transition entre les architectures 32 et 64 bits, et "unsigned long long int" ne signifie pas la même chose sur les deux.
BD à Rivenhill

Réponses:

483

Utilisez le modificateur ll (el-el) long-long avec la conversion u (non signé). (Fonctionne sous Windows, GNU).

printf("%llu", 285212672);
John Downey
la source
11
Ou pour être précis, c'est pour GNU libc, et ne fonctionne pas avec le runtime C de Microsoft.
Mark Baker,
168
Ce n'est pas une chose Linux / UNIX, le modificateur de longueur "ll" a été ajouté à la norme C en C99, s'il ne fonctionne pas dans "Microsoft C", c'est parce qu'ils ne sont pas conformes aux normes.
Robert Gamble
12
Fonctionne pour moi dans VS2008. De plus, pour autant que je m'en souvienne, le compilateur MS C (lorsqu'il est configuré pour compiler le C droit) est censé être conforme à la conception C90; C99 a introduit des choses que tout le monde n'a pas appréciées.
ス ー パ ー フ ァ ミ コ ン
6
Une chose à garder à l'esprit ici est que si vous passez plusieurs long longarguments à printfet utilisez le mauvais format pour l'un d'entre eux, disons à la %dplace de %lld, alors même les arguments imprimés après le mauvais peuvent être complètement désactivés (ou même provoquer un printfcrash) ). Essentiellement, les arguments variables sont passés à printf sans aucune information de type, donc si la chaîne de format est incorrecte, le résultat est imprévisible.
dmitrii
1
Heard Herb Sutter a déclaré dans une interview que les clients de Microsoft ne demandaient pas C99, donc leur compilateur C pur a été gelé à C90. Cela s'applique si vous compilez en C. Si vous compilez en C ++, comme d'autres l'ont noté ci-dessus, ça devrait aller.
ahcox
90

Vous pouvez essayer d' utiliser la bibliothèque inttypes.h qui vous donne types tels que int32_t, int64_t, uint64_tetc. Vous pouvez ensuite utiliser ses macros telles que:

uint64_t x;
uint32_t y;

printf("x: %"PRId64", y: %"PRId32"\n", x, y);

Ceci est "garanti" pour ne pas vous causer le même problème que long, unsigned long longetc., car vous n'avez pas à deviner le nombre de bits dans chaque type de données.

Nathan Fellman
la source
où ceux PRId64- ci , les PRId32macros définies?
happy_marmoset
4
@happy_marmoset: ils sont définis dansinttypes.h
Nathan Fellman
4
Je pense que vous avez besoin PRIu64et PRIu32pour les entiers non signés.
Lasse Kliemann
1
Est inttypes.hstandard? N'est-ce pas stdint.h?
MD XF
2
Notez que ces types de largeur exacte sont facultatifs , car il existe des architectures qui n'ont pas de types entiers de ces largeurs exactes. Seuls les types leastXet fastX(qui peuvent en fait être plus larges que ceux indiqués) sont obligatoires.
DevSolar
78

%d-> pour int

%u-> pour unsigned int

%ld-> pour long intoulong

%lu-> pour unsigned long intou long unsigned intouunsigned long

%lld-> pour long long intoulong long

%llu-> pour unsigned long long intouunsigned long long

Shivam Chauhan
la source
Existe-t-il un spécificateur de format comme le nombre de chiffres à afficher, une justification à gauche ou à droite pour% lld ou% llu?
Asam Padeh
40

Pour une longue période (ou __int64) en utilisant MSVS, vous devez utiliser% I64d:

__int64 a;
time_t b;
...
fprintf(outFile,"%I64d,%I64d\n",a,b);    //I is capital i

la source
37

En effet,% llu ne fonctionne pas correctement sous Windows et% d ne peut pas gérer les entiers 64 bits. Je suggère d'utiliser plutôt PRIu64 et vous constaterez qu'il est également portable pour Linux.

Essayez plutôt ceci:

#include <stdio.h>
#include <inttypes.h>

int main() {
    unsigned long long int num = 285212672; //FYI: fits in 29 bits
    int normalInt = 5;
    /* NOTE: PRIu64 is a preprocessor macro and thus should go outside the quoted string. */
    printf("My number is %d bytes wide and its value is %" PRIu64 ". A normal number is %d.\n", sizeof(num), num, normalInt);
    return 0;
}

Production

My number is 8 bytes wide and its value is 285212672. A normal number is 5.
Paul Hargreaves
la source
+1 pour la référence à PRIu64, que je n'avais jamais vu, mais cela ne semble pas portable pour Linux 64 bits (au moins) car PRIu64 se développe en "lu" au lieu de "llu".
BD à Rivenhill
8
Et pourquoi serait-ce mauvais? Un long est une valeur 64 bits sur Linux 64 bits, comme sur tous les autres systèmes d'exploitation, à l'exception de Windows.
Ringding
@BDatRivenhill Linux / Unix utilise LP64 dont la longueur est de 64 bits
phuclv
1
cependant, pour le rendre plus portable, utilisez-le à la int64_tplace car il peut bien y avoir des implémentations avec long long plus grand que long
phuclv
cela devrait être au top! - une petite mise à jour: erreur: suffixe invalide sur littéral; C ++ 11 nécessite un espace entre le littéral et l'identifiant [-Wreserved-user-defined-literal]
tofutim
14

Sous Linux c'est le cas %lluet sous Windows c'est%I64u

Bien que j'ai trouvé que cela ne fonctionne pas dans Windows 2000, il semble y avoir un bogue!

Adam Pierce
la source
avec Windows, (ou au moins, avec le compilateur Microsoft C pour Windows), il y a aussi% I64d,% I32u et% I32d
JustJeff
1
Qu'est-ce que cela a à voir avec Windows 2000? La bibliothèque C est celle qui gère printf.
CMircea
1
Exactement ce que j'ai observé. J'ai écrit une application qui utilisait cette construction et cela fonctionnait parfaitement sur WinXP mais crachait des ordures sur Win2k. Peut-être que c'est quelque chose à voir avec un appel système que la bibliothèque C fait au noyau, peut-être que c'est quelque chose à voir avec Unicode, qui sait. Je me souviens avoir dû contourner cela en utilisant _i64tot () ou quelque chose comme ça.
Adam Pierce
7
On dirait que MS exerce à nouveau sa "liberté d'innover" ... ;-)
Dronz
Le problème Win2k / Win9x est probablement dû au fait que le unsigned long longtype de données est relativement nouveau (à l'époque, avec la norme C99) mais que les compilateurs C (y compris MinGW / GCC) utilisent l'ancien runtime Microsoft C qui ne supportait que la spécification C89. Je n'ai accès qu'à des documents API Windows vraiment anciens et raisonnablement récents. Il est donc difficile de dire exactement quand le I64usupport a été supprimé. Mais cela ressemble à l'ère XP.
veganaiZe
8

Compilez-le au format x64 avec VS2005:

% llu fonctionne bien.

Sablonneux
la source
3

En plus de ce que les gens écrivaient il y a des années:

  • vous pourriez obtenir cette erreur sur gcc / mingw:

main.c:30:3: warning: unknown conversion type character 'l' in format [-Wformat=]

printf("%llu\n", k);

Ensuite, votre version de mingw n'est pas par défaut c99. Ajouter ce drapeau du compilateur: -std=c99.

Bernd Elkemann
la source
3

Apparemment, personne n'a mis au point une solution multiplateforme * depuis plus d'une décennie depuis [l'année] 2008, je vais donc ajouter la mienne 😛. Plz upvote. (Blague. Je m'en fiche.)

Solution: lltoa()

Comment utiliser:

#include <stdlib.h> /* lltoa() */
// ...
char dummy[255];
printf("Over 4 bytes: %s\n", lltoa(5555555555, dummy, 10));
printf("Another one: %s\n", lltoa(15555555555, dummy, 10));

Exemple de l'OP:

#include <stdio.h>
#include <stdlib.h> /* lltoa() */

int main() {
    unsigned long long int num = 285212672; // fits in 29 bits
    char dummy[255];
    int normalInt = 5;
    printf("My number is %d bytes wide and its value is %s. "
        "A normal number is %d.\n", 
        sizeof(num), lltoa(num, dummy, 10), normalInt);
    return 0;
}

Contrairement à la %lldchaîne de format d'impression, celle-ci fonctionne pour moi sous GCC 32 bits sous Windows.

*) Eh bien, presque multi-plateforme. Dans MSVC, vous avez apparemment besoin _ui64toa()de lltoa().

7vujy0f0hy
la source
1
Je n'en ai pas lltoa.
Antti Haapala
1

Les choses non standard sont toujours étranges :)

pour la partie longue et longue sous GNU c'est L, llouq

et sous les fenêtres je crois que c'est llseulement

étincelles
la source
1

Hex:

printf("64bit: %llp", 0xffffffffffffffff);

Production:

64bit: FFFFFFFFFFFFFFFF
lama12345
la source
Très agréable! je me demandais comment je pouvais l'obtenir en représentation hexadécimale
0xAK
Mais, presque tous les compilateurs C ++ et C donnent l'avertissement: avertissement: utilisation du modificateur de longueur «ll» avec le caractère de type «p» [-Wformat =]
Seshadri R
2
cette réponse totalement brisée a un comportement doublement indéfini et ne commence même pas à répondre à la question .
Antti Haapala
@AnttiHaapala Vous dites que cette réponse est totalement brisée avec un comportement doublement indéfini, pouvez-vous élaborer ou dois-je simplement la supprimer? Ou le garder comme un bon mauvais exemple?
lama12345
0

Eh bien, une façon est de le compiler en x64 avec VS2008

Cela fonctionne comme vous vous en doutez:

int normalInt = 5; 
unsigned long long int num=285212672;
printf(
    "My number is %d bytes wide and its value is %ul. 
    A normal number is %d \n", 
    sizeof(num), 
    num, 
    normalInt);

Pour le code 32 bits, nous devons utiliser le spécificateur de format __int64 correct% I64u. Alors ça devient.

int normalInt = 5; 
unsigned __int64 num=285212672;
printf(
    "My number is %d bytes wide and its value is %I64u. 
    A normal number is %d", 
    sizeof(num),
    num, normalInt);

Ce code fonctionne pour les compilateurs VS 32 et 64 bits.

vzczc
la source
Essayez un nombre réel de 64 bits au lieu de '285212672' et je ne pense pas que le premier exemple fonctionne correctement, compilé sur n'importe quelle cible.
dyasta