Cách in kiểu int64_t bằng C


298

Tiêu chuẩn C99 có các kiểu số nguyên với kích thước byte như int64_t. Tôi đang sử dụng đoạn mã sau:

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

và tôi nhận được cảnh báo trình biên dịch này:

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

Tôi đã thử với:

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

Nhưng tôi nhận được cảnh báo tương tự. Tôi đang sử dụng trình biên dịch này:

~/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)

Tôi nên sử dụng định dạng nào để in biến my_int mà không có cảnh báo?


Câu trả lời:


420

Đối với int64_tloại:

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

cho uint64_tloại:

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

bạn cũng có thể sử dụng PRIx64để in ở hệ thập lục phân.

cppreference.com có ​​một danh sách đầy đủ các macro có sẵn cho tất cả các loại bao gồm intptr_t( PRIxPTR). Có các macro riêng cho scanf, như SCNd64.


Một định nghĩa điển hình của PRIu16 sẽ là "hu", do đó, việc nối chuỗi liên tục ngầm xảy ra vào thời gian biên dịch.

Để mã của bạn có thể di động hoàn toàn, bạn phải sử dụng PRId32và tiếp tục để in int32_t"%d"tương tự để in int.


18
Danh sách đầy đủ các hằng số macro định dạng: en.cppreference.com/w/cpp/types/integer
Massood Khaari

12
Và, nếu sử dụng C ++ trên Linux, hãy chắc chắn #define __STDC_FORMAT_MACROStrước khi đưa vào inttypes.h.
csl

17
PRId64là một macro mà bên trong dịch sang "lld". Vì vậy, nó cũng tốt như viết printf("%lld\n", t);Xem mô tả: qnx.com/developers/docs/6.5.0/NH
Gaurav

24
@Gaurav, điều đó đúng trên một số nền tảng, nhưng không phải trên tất cả. Ví dụ, trên máy Linux amd64 của tôi, PRId64 được định nghĩa là ld. Tính di động là lý do cho vĩ mô.
Ethan T

10
Tôi nghĩ rằng với một số nỗ lực thêm, họ có thể khiến nó trở nên đáng ghét hơn
Pavel P

65

Cách C99 là

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

Hoặc bạn có thể đúc!

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

Nếu bạn bị mắc kẹt với triển khai C89 (đáng chú ý là Visual Studio), có lẽ bạn có thể sử dụng nguồn mở <inttypes.h>(và <stdint.h>): http://code.google.com.vn/p/msinttypes/


Khi sử dụng msinttypes từ liên kết code.google.com, tôi cần xác định __STDC_FORMAT_MACROS. Xem stackoverflow.com/questions/8132399/how-to-printf-uint64-t .
ariscris

Cảm ơn những người đứng đầu, @ariscris. Dường như macro chỉ được yêu cầu cho C ++. Các định nghĩa trong các mã liên quan đến là bên trong một#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS)
PMG

19

Với C99, %jbộ điều chỉnh độ dài cũng có thể được sử dụng với họ hàm printf để in các giá trị loại int64_tuint64_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;
}

Biên dịch mã này gcc -Wall -pedantic -std=c99không tạo ra cảnh báo và chương trình in kết quả đầu ra dự kiến:

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

Điều này là theo printf(3)hệ thống Linux của tôi (trang con người nói cụ thể jđược sử dụng để chỉ ra một chuyển đổi thành intmax_thoặc uintmax_t; trong stdint.h của tôi, cả hai int64_tintmax_tđược đánh máy theo cách chính xác và tương tự như vậy uint64_t). Tôi không chắc chắn nếu điều này là hoàn toàn di động cho các hệ thống khác.


12
Nếu %jdprnts an intmax_t, lời gọi chính xác sẽ là printf("a=%jd (0x%jx)", (intmax_t) a, (intmax_t) a). Không có gì đảm bảo rằng int64_tintmax_tcùng loại và nếu không, hành vi này không được xác định.
dùng4815162342

4
Bạn có thể sử dụng một %jdcách hợp lý để in int64_tcác giá trị nếu bạn chuyển đổi chúng thành rõ ràng intmax_ttrước khi chuyển chúng sang printf: printf("a=%jd\n", (intmax_t)a). Điều này tránh sự xấu xí (IMHO) của các <inttypes.h>macro. Tất nhiên điều này giả định rằng sự hỗ trợ thực hiện của bạn %jd, int64_tintmax_t, tất cả đều đã được bổ sung bởi C99.
Keith Thompson

2
@KeithThndry 'Ugliness' đang đưa nó đi rất xa rất xa người bạn đời tốt bụng. Nó hoàn toàn gớm ghiếc. Thật kinh khủng. Thật là buồn nôn. Thật xấu hổ là những gì nó được. Hoặc ít nhất họ nên xấu hổ, rất nhiều đã giới thiệu này. Tôi chưa bao giờ thấy các macro này nhưng hãy làm những gì câu trả lời này và các nhận xét - bao gồm của bạn - đề xuất.
Pryftan

@Pryftan Tôi hoàn toàn không thấy chúng xấu xí như bạn - và tôi không chắc chắn làm thế nào chúng có thể được định nghĩa theo cách ít xấu xí hơn mà không thay đổi ngôn ngữ.
Keith Thompson

@KeithThndry Vâng, tôi rất biết ơn bạn ít nhất cũng nhấn mạnh từ 'khá'. Thật ra nó không thành vấn đề. Tôi không thấy lý do tại sao các macro phải ở đó mặc dù. Như bạn nói bạn có thể di chuyển một cách hợp lý ... v.v. Nhưng sau đó tôi cũng thấy rằng sự gia tăng số lượng từ khóa cũng đã vượt quá tầm tay.
Pryftan

12

Đến từ thế giới nhúng, nơi mà ngay cả uclibc không phải lúc nào cũng có sẵn và mã như

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

đang in bạn tào lao hoặc hoàn toàn không hoạt động - tôi luôn sử dụng một trình trợ giúp nhỏ, cho phép tôi kết xuất chính xác uint64_t hex:

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

Nếu bạn đang đối mặt với vấn đề này đối với một ứng dụng nhúng, thì đây là thứ bạn đang tìm kiếm. Giải pháp này đã làm việc cho tôi. Thnx @ataraxic.
Logan859

8

Trong môi trường windows, sử dụng

%I64d

trong Linux, sử dụng

%lld

18
%lldlà định dạng cho long long int, không nhất thiết phải giống như int64_t. <stdint.h>có một macro cho định dạng chính xác cho int64_t; xem câu trả lời của ouah .
Keith Thompson

@KeithThndry Tuy nhiên, vì long longít nhất là 64 bit, printf("%lld", (long long)x);nên hoạt động, ngoại trừ -0x8000000000000000, không thể biểu diễn được long longnếu loại đó không sử dụng bổ sung hai.
Pascal Cuoq

@PascalCuoq: Có, nó nên hoạt động với dàn diễn viên (và ngoại lệ bạn đề cập là rất khó xảy ra, chỉ áp dụng cho một hệ thống hỗ trợ hai phần bù nhưng không sử dụng cho long long).
Keith Thompson

-3

//VC6.0 (386 & tốt hơn)

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

Trân trọng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.