Printf kullanarak imzasız uzun uzun int formatını nasıl biçimlendirirsiniz?


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;
}

Çıktı:

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

Bu beklenmedik sonucun unsigned long long int. Size nasıl printf()bir unsigned long long int?


2
Ben sadece kodunuzu (% llu ile) gcc ile derledim ve çıktı doğru olanıydı. Derleyiciye herhangi bir seçenek aktarıyor musunuz?
Juan

2
Samsung bada'nın newlib'in "% lld" değerini desteklemediğini unutmayın: developer.bada.com/forum/…
RzR


Ben stdint.h kullanarak ve değişkeninizdeki bit sayısı hakkında açık olmanızı öneririm. Hala 32 ve 64 bit mimariler arasında bir geçiş dönemindeyiz ve "imzasız uzun uzun int" her ikisi için de aynı anlama gelmiyor.
BD, Rivenhill'de

Yanıtlar:


483

U (imzasız) dönüşümüyle ll (el-el) uzun-uzun değiştiricisini kullanın. (Pencerelerde çalışır, GNU).

printf("%llu", 285212672);

11
Veya kesin olarak GNU libc içindir ve Microsoft'un C çalışma zamanı ile çalışmaz.
Mark Baker

168
Bu bir Linux / UNIX işi değil, "ll" uzunluk değiştiricisi C99'da Standart C'ye eklenmiş, eğer "Microsoft C" de çalışmıyorsa standartlara uygun olmadıkları içindir.
Robert Gamble

12
VS2008'de benim için çalışıyor. Dahası, hatırladığım kadarıyla MS C Derleyicisinin (düz C derlemek için ayarlandığında) tasarım ile C90 uyumlu olması gerekiyordu; C99, herkesin sevmediği bazı şeyler tanıttı.
ス ー パ ー フ ァ ミ コ

6
Burada akılda tutulması gereken bir şey , bunlardan birine birden fazla long longargüman geçiriyorsanız printfve bunlardan biri için yanlış biçimi kullanırsanız , bunun %dyerine , yanlış %lldolandan sonra yazdırılan argümanların bile tamamen kapalı olabileceği (hatta printfçökmesine neden olabileceği) ). Temel olarak, değişken argümanları herhangi bir tür bilgisi olmadan printf'e iletilir, bu nedenle format dizesi yanlışsa sonuç tahmin edilemez.
dmitrii

1
Heard Herb Sutter bir röportajda Microsoft müşterilerinin C99 istemediğini, bu yüzden saf C derleyicisinin C90'da dondurulduğunu söyledi. Bu, C olarak derliyorsanız geçerlidir. C ++ olarak derlerseniz, yukarıda belirtildiği gibi, iyi olmalısınız.
ahcox

90

Sen seni gibi türleri verir inttypes.h kitaplığını kullanarak deneyebilirsiniz int32_t, int64_t, uint64_tvb Ardından gibi onun makroları kullanabilirsiniz:

uint64_t x;
uint32_t y;

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

Her veri türünde kaç bit olduğunu tahmin etmek zorunda olmadığınızdan, bu long, unsigned long longvb. İle aynı sorunu vermemeniz için "garanti edilir" .


bunlar nerede PRId64, PRId32makrolar tanımlandı?
happy_marmoset

4
@happy_marmoset: onlar tanımlandıinttypes.h
Nathan Fellman

4
Bence PRIu64ve PRIu32imzasız tamsayılara ihtiyacın var .
Lasse Kliemann

1
inttypes.hstandart? Öyle değil mi stdint.h?
MD XF

2
Bu tam genişlik türlerinin isteğe bağlı olduğunu unutmayın , çünkü orada bu tam genişliklerde tamsayı türlerine sahip olmayan mimariler vardır . Yalnızca leastXve fastXtürleri (aslında belirtilenden daha geniş olabilir) zorunludur.
DevSolar

78

%d-> için int

%u-> için unsigned int

%ld-> için long intveyalong

%lu-> için unsigned long intveya long unsigned intveyaunsigned long

%lld-> için long long intveyalong long

%llu-> için unsigned long long intveyaunsigned long long


Görüntülenecek basamak sayısı,% lld veya% llu için sola veya sağa yaslama gibi bir biçim belirteci var mı?
Asam Padeh

40

MSVS kullanan uzun uzun (veya __int64) için% I64d kullanmalısınız:

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

37

Çünkü% llu Windows altında düzgün çalışmıyor ve% d 64 bit tamsayıları işleyemiyor. Bunun yerine PRIu64 kullanmanızı öneririm ve Linux için de taşınabilir olduğunu göreceksiniz.

Bunun yerine şunu deneyin:

#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;
}

Çıktı

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

Daha önce hiç görmediğim PRIu64 referansı için +1, ancak 64 bit Linux'a taşınabilir değil (en azından) çünkü PRIu64 "llu" yerine "lu" ya genişliyor.
BD, Rivenhill'de

8
Ve bu neden kötü olur? Uzun, Windows dışındaki diğer tüm işletim sistemlerinde olduğu gibi 64 bit Linux'ta 64 bitlik bir değerdir.
Ringing

@BDatRivenhill Linux / Unix, 64 bit uzunluğunda olan LP64 kullanıyor
phuclv

1
Ancak, daha taşınabilir hale getirmek için, int64_tbunun yerine kullanın çünkü uzun uzun uzun uzun daha büyük bazı uygulamalar olabilir
phuclv

bu en üste gelmeli! - küçük bir güncelleme: hata: gerçekte geçersiz sonek; C ++ 11 değişmez ve tanımlayıcı arasında bir boşluk gerektirir [-Wreserved-user-definition-literal]
tofutim

14

Linux'ta öyle %lluve Windows'ta%I64u

Windows 2000'de çalışmadığını fark etsem de, orada bir hata var gibi görünüyor!


pencerelerle (veya en azından pencereler için microsoft C derleyicisiyle) ayrıca% I64d,% I32u ve% I32d
JustJeff

1
Windows 2000 ile ne ilgisi var? C kütüphanesi printf'i işleyen kütüphanedir.
CMircea

1
Sadece gözlemledim. Bu yapıyı kullanan bir uygulama yazdım ve WinXP'de mükemmel çalıştı ancak Win2k'de çöp tükürdü. Belki de C kütüphanesinin çekirdeğe yaptığı bir sistem çağrısı ile ilgisi vardır, belki de Unicode ile ilgisi vardır. _İ64tot () veya bunun gibi bir şey kullanarak etrafında çalışmak zorunda hatırlıyorum.
Adam Pierce

7
MS tekrar "yenilik özgürlüğünü" kullanıyor gibi görünüyor; ;-)
Dronz

Win2k / Win9x sorununun nedeni büyük olasılıkla unsigned long longveri türünün nispeten yeni olması (o sırada C99 standardı ile) olmakla birlikte, yalnızca C89 özelliğini destekleyen eski Microsoft C çalışma zamanını kullanan C derleyicilerinin (MinGW / GCC dahil) olmasıdır. Yalnızca gerçekten eski ve makul düzeyde yeni Windows API belgelerine erişimim var. Bu yüzden I64udesteğin ne zaman bırakıldığını söylemek zor . Ama XP-dönemi gibi geliyor.
veganaiZe

8

VS2005 ile x64 olarak derleyin:

% llu iyi çalışıyor.


3

İnsanların yıllar önce yazdıklarına ek olarak:

  • gcc / mingw'de bu hatayı alabilirsiniz:

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

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

Sonra mingw sürümünüz varsayılan olarak c99 olarak ayarlanmaz. Bu derleyici bayrağı ekleyin: -std=c99.


3

Görünüşe göre hiç kimse on yıldan fazla bir süredir çoklu platform * çözümü bulamadı 2008 yılından bu yana bulamadı, bu yüzden benimkini ekleyeceğim. Plz upvote. (Şaka. Umurumda değil.)

Çözüm: lltoa()

Nasıl kullanılır:

#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));

OP örneği:

#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;
}

%lldYazdırma biçimi dizesinin aksine , bu benim için Windows'ta 32 bit GCC altında çalışır .

*) Neredeyse çok platformlu. MSVC'de, görünüşe göre _ui64toa()yerine ihtiyacınız var lltoa().


1
Bende yok lltoa.
Antti Haapala

1

Standart olmayan şeyler her zaman gariptir :)

GNU altındaki uzun uzun kısım için L, llveyaq

ve pencerelerin altında llsadece


1

hex:

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

Çıktı:

64bit: FFFFFFFFFFFFFFFF

Çok hoş! nasıl hex temsilinde alabilirim merak ediyordum
0xAK

Ancak, hemen hemen tüm C ++ ve C derleyicileri uyarı verir: uyarı: 'p' tipi karakterli 'll' uzunluk değiştiricinin kullanımı [-Wformat =]
Seshadri R

2
bu son derece kırılmış cevap iki kat tanımsız davranışa sahiptir ve hatta soruyu cevaplamaya başlamamaktadır .
Antti Haapala

@AnttiHaapala Bu cevabın iki kat tanımsız davranışla tamamen bozulduğunu söylüyorsunuz, detaylandırabilir misiniz yoksa silebilir miyim? Yoksa iyi bir kötü örnek olarak mı?
lama12345

0

Bir yolu VS2008 ile x64 olarak derlemektir

Bu beklediğiniz gibi çalışır:

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);

32 bit kod için,% I64u doğru __int64 format belirleyicisini kullanmamız gerekir. Böylece olur.

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);

Bu kod hem 32 hem de 64 bit VS derleyici için çalışır.


'285212672' yerine gerçek bir 64 bit sayı deneyin ve ilk örneğin herhangi bir hedefe derlenmiş doğru çalıştığına inanmıyorum.
dyasta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.