C dilinde int64_t türü nasıl yazdırılır


298

C99 standardı, int64_t gibi bayt boyutlu tamsayı türlerine sahiptir. Aşağıdaki kodu kullanıyorum:

#include <stdio.h>
#include <stdint.h>
int64_t my_int = 999999999999999999;
printf("This is my_int: %I64d\n", my_int);

ve bu derleyici uyarısını alıyorum:

warning: format ‘%I64d expects type int’, but argument 2 has type int64_t

İle denedim:

printf("This is my_int: %lld\n", my_int); // long long decimal

Ama aynı uyarıyı alıyorum. Bu derleyiciyi kullanıyorum:

~/dev/c$ cc -v
Using built-in specs.
Target: i686-apple-darwin10
Configured with: /var/tmp/gcc/gcc-5664~89/src/configure --disable-checking --enable-werror --prefix=/usr --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin10 --program-prefix=i686-apple-darwin10- --host=x86_64-apple-darwin10 --target=i686-apple-darwin10 --with-gxx-include-dir=/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Apple Inc. build 5664)

Bir uyarım olmadan my_int değişkenimi yazdırmak için hangi biçimi kullanmalıyım?


Yanıtlar:


420

For int64_ttürü:

#include <inttypes.h>
int64_t t;
printf("%" PRId64 "\n", t);

için uint64_ttipi:

#include <inttypes.h>
uint64_t t;
printf("%" PRIu64 "\n", t);

PRIx64onaltılık olarak yazdırmak için de kullanabilirsiniz .

cppreference.com,intptr_t ( PRIxPTR) dahil tüm türler için kullanılabilir makroların tam listesine sahiptir . Scanf için ayrı makrolar vardır SCNd64.


PRIu16 için tipik bir tanım "hu", derleme zamanında örtülü dize-sabit birleştirme olur.

Kodunuzu tam taşınabilir olması için, kullanmak gerekir PRId32ve bu yüzden baskı için üzerinde int32_tve "%d"ya baskı için benzer int.


18
Biçimlendirme makro sabitlerinin tam listesi: en.cppreference.com/w/cpp/types/integer
Massood Khaari

12
Ve Linux'ta C ++ kullanıyorsanız, #define __STDC_FORMAT_MACROSeklemeden önce mutlaka emin olun inttypes.h.
csl

17
PRId64dahili olarak çevrilen bir makrodur "lld". Yani, yazmak kadar iyi printf("%lld\n", t);Açıklamaya bakın: qnx.com/developers/docs/6.5.0/…
Gaurav

24
@Gaurav, bu bazı platformlarda doğrudur, ancak hepsi için geçerli değildir. Amd64 Linux makinemde, örneğin, PRId64 olarak tanımlanır ld. Taşınabilirlik makronun sebebidir.
Ethan T

10
Biraz ekstra çaba ile daha da iğrenç hale getirebilir düşünüyorum
Pavel P

65

C99 yolu

#include <inttypes.h>
int64_t my_int = 999999999999999999;
printf("%" PRId64 "\n", my_int);

Ya da oyuncu olabilirsiniz!

printf("%ld", (long)my_int);
printf("%lld", (long long)my_int); /* C89 didn't define `long long` */
printf("%f", (double)my_int);

Bir C89 uygulaması (özellikle Visual Studio) ile sıkışmışsanız, belki de bir açık kaynak <inttypes.h>(ve <stdint.h>) kullanabilirsiniz: http://code.google.com/p/msinttypes/


Code.google.com bağlantısından msinttypes kullanırken __STDC_FORMAT_MACROS tanımlamam gerekiyor. Bkz. Stackoverflow.com/questions/8132399/how-to-printf-uint64-t .
ariscris

Uyarı için teşekkürler, @ariscris. Makro sadece C ++ için gerekli gibi görünüyor. Bağlantılı koddaki tanımlar bir#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
pmg

19

C99 ile %juzunluk değiştirici de türünün değerlerini yazdırmak için printf ailesi işlevlerde kullanılabilir int64_tve uint64_t:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[])
{
    int64_t  a = 1LL << 63;
    uint64_t b = 1ULL << 63;

    printf("a=%jd (0x%jx)\n", a, a);
    printf("b=%ju (0x%jx)\n", b, b);

    return 0;
}

Bu kodu gcc -Wall -pedantic -std=c99derlemek hiçbir uyarı üretmez ve program beklenen çıktıyı yazdırır:

a=-9223372036854775808 (0x8000000000000000)
b=9223372036854775808 (0x8000000000000000)

Bu printf(3)benim Linux sistemime göre (man sayfası özellikle jbir intmax_tveya uintmax_t; stdint.h dosyamda bir dönüşümü belirtmek için kullanıldığını int64_tve intmax_ther ikisinin de tam olarak aynı şekilde ve benzer şekilde tanımlandığını söylüyor uint64_t). Bunun diğer sistemlere mükemmel taşınabilir olup olmadığından emin değilim.


12
Eğer %jdprnts an intmax_t, doğru çağırma olur printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a). Orada garantisi değildir int64_tve intmax_taynı tip ve bunlar değilse, davranış tanımlanmamış.
user4815162342

4
Sen portably kullanabilirsiniz %jdyazdırmak için int64_tdeğerler ise açıkça çevirebiliriz intmax_tgeçirmeden önce printf: printf("a=%jd\n", (intmax_t)a). Bu, <inttypes.h>makroların (IMHO) çirkinliğini önler . Tabii bu uygulama desteklediği varsayar %jd, int64_tve intmax_t, hepsi C99 tarafından eklenmiştir.
Keith Thompson

2
@ KeithThompson 'Ugliness' çok nazik bir şekilde dostum. Kesinlikle iğrenç. Korkunç. Bulantı. Bu utanç vericidir. Ya da en azından bunu getiren çok utanç vermeliler. Bu makroları hiç görmedim ama bu cevabı ve yorumları - sizinki dahil - önerin.
Pryftan

Ben yok @Pryftan oldukça sizin kadar onları oldukça çirkin bulmak - ve onlar dil değişiklik olmadan daha az çirkin bir şekilde tanımlanabilir nasıl tüm emin değilim.
Keith Thompson

@KeithThompson En azından 'oldukça' kelimesine vurgu yaptığınız için minnettarım. Aslında önemli değil. Makroların neden orada olması gerektiğini anlamıyorum. Dediğiniz gibi portatif olarak yapabilirsiniz ... Vb Ama sonra da anahtar kelime sayısındaki artış da elden olduğunu bulmak.
Pryftan

12

Uclibc'in her zaman mevcut olmadığı gömülü dünyadan geliyor ve

uint64_t myval = 0xdeadfacedeadbeef; printf("%llx", myval);

bok baskı ya da hiç çalışmıyor - ben her zaman uint64_t hex düzgün dökümü sağlar küçük bir yardımcı kullanın:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

char* ullx(uint64_t val)
{
    static char buf[34] = { [0 ... 33] = 0 };
    char* out = &buf[33];
    uint64_t hval = val;
    unsigned int hbase = 16;

    do {
        *out = "0123456789abcdef"[hval % hbase];
        --out;
        hval /= hbase;
    } while(hval);

    *out-- = 'x', *out = '0';

    return out;
}

Gömülü bir uygulama için bu sorunla karşı karşıyaysanız, aradığınız şey budur. Bu çözüm benim için çalıştı. Thnx @ataraxic.
Logan859

8

Windows ortamında,

%I64d

Linux'ta,

%lld

18
%lldiçin biçimi long long intolup, değil mutlaka aynı int64_t. <stdint.h>doğru biçim için bir makroya sahiptir int64_t; ouah'ın cevabına bakınız .
Keith Thompson

@KeithThompson Ancak, belki de -0x8000000000000000 hariç long long, en az 64 bit printf("%lld", (long long)x);olduğu için long long, bu tür iki tamamlayıcı kullanılmıyormuş gibi gösterilemez.
Pascal Cuoq

@PascalCuoq: Evet, oyuncu kadrosu ile çalışmalı (ve bahsettiğiniz istisna pek olası değil, sadece ikisinin tamamlayıcısını destekleyen ancak bunun için kullanmayan bir sisteme başvuruyor long long).
Keith Thompson

-3

//VC6.0 (386 ve daha iyisi)

    __int64 my_qw_var = 0x1234567890abcdef;

    __int32 v_dw_h;
    __int32 v_dw_l;

    __asm
        {
            mov eax,[dword ptr my_qw_var + 4]   //dwh
            mov [dword ptr v_dw_h],eax

            mov eax,[dword ptr my_qw_var]   //dwl
            mov [dword ptr v_dw_l],eax

        }
        //Oops 0.8 format
    printf("val = 0x%0.8x%0.8x\n", (__int32)v_dw_h, (__int32)v_dw_l);

Saygılarımızla.

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.