Làm thế nào để bạn định dạng một int dài dài không dấu bằng cách sử dụng 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;
}

Đầu ra:

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

Tôi cho rằng kết quả bất ngờ này là từ việc in unsigned long long int. Làm thế nào để bạn printf()một unsigned long long int?


2
Tôi vừa biên dịch mã của bạn (với% llu) với gcc và đầu ra là chính xác. Bạn đang chuyển bất kỳ tùy chọn cho trình biên dịch?
Juan

2
Lưu ý rằng newlib của samsung bada dường như không hỗ trợ "% lld": developer.bada.com/forum/
mẹo


Tôi sẽ đề nghị sử dụng stdint.h và rõ ràng về số lượng bit trong biến của bạn. Chúng ta vẫn đang trong giai đoạn chuyển đổi giữa các kiến ​​trúc 32 và 64 bit, và "int dài long int" không có nghĩa là điều tương tự trên cả hai.
BD tại Rive dốc

Câu trả lời:


483

Sử dụng công cụ sửa đổi dài (ll-el) với chuyển đổi u (không dấu). (Hoạt động trong windows, GNU).

printf("%llu", 285212672);

11
Hay nói chính xác là nó dành cho GNU libc và không hoạt động với thời gian chạy C của Microsoft.
Đánh dấu Baker

168
Đây không phải là điều Linux / UNIX, công cụ sửa đổi độ dài "ll" đã được thêm vào Standard C trong C99, nếu nó không hoạt động trong "Microsoft C" thì đó là do chúng không tuân thủ tiêu chuẩn.
Robert Gamble

12
Hoạt động cho tôi trong VS2008. Hơn nữa, theo như tôi nhớ thì Trình biên dịch MS C (khi được thiết lập để biên dịch thẳng C) được cho là tuân thủ C90 theo thiết kế; C99 giới thiệu một số điều mà không phải ai cũng thích.
ス ー パ コ

6
Một lưu ý ở đây là nếu bạn chuyển nhiều long longđối số sang printfvà sử dụng định dạng sai cho một trong số chúng, hãy nói %dthay vì %lld, ngay cả các đối số được in sau khi đối số không chính xác có thể bị tắt hoàn toàn (hoặc thậm chí có thể gây ra sự printfcố ). Về cơ bản, các đối số biến được truyền cho printf mà không có bất kỳ thông tin loại nào, vì vậy nếu chuỗi định dạng không chính xác, kết quả là không thể đoán trước.
dmitrii

1
Heard Herb Sutter nói trong một cuộc phỏng vấn rằng khách hàng của Microsoft không yêu cầu C99 nên trình biên dịch C thuần túy của họ đã bị đóng băng tại C90. Điều đó áp dụng nếu bạn đang biên dịch thành C. Nếu bạn biên dịch thành C ++, như những người khác đã lưu ý ở trên, bạn sẽ ổn thôi.
ahcox

90

Bạn có thể muốn thử sử dụng thư viện inttypes.h cung cấp cho bạn các loại như int32_t, int64_t, uint64_tvv sau đó bạn có thể sử dụng các macro của nó như:

uint64_t x;
uint32_t y;

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

Điều này được "đảm bảo" để không gây rắc rối cho bạn như long, unsigned long longv.v., vì bạn không phải đoán có bao nhiêu bit trong mỗi loại dữ liệu.


Những cái này PRId64, PRId32macro được định nghĩa ở đâu?
happy_marmoset

4
@happy_marmoset: chúng được xác định tronginttypes.h
Nathan Fellman

4
Tôi nghĩ rằng bạn cần PRIu64PRIu32cho số nguyên không dấu.
Lasse Kliemann

1
inttypes.htiêu chuẩn? Có phải vậy stdint.hkhông?
MD XF

2
Lưu ý rằng các loại chiều rộng chính xác này là tùy chọn , vì có các kiến ​​trúc ngoài đó không có các loại số nguyên của các chiều rộng chính xác đó. Chỉ leastXfastXcác loại (có thể thực sự rộng hơn chỉ định) là bắt buộc.
DevSolar

78

%d-> cho int

%u-> cho unsigned int

%ld-> cho long inthoặclong

%lu-> cho unsigned long inthoặc long unsigned inthoặcunsigned long

%lld-> cho long long inthoặclong long

%llu-> cho unsigned long long inthoặcunsigned long long


Có định dạng định dạng như số chữ số để hiển thị, chứng minh trái hay phải cho% lld hoặc% llu không?
Asam Padeh

40

Để sử dụng MSVS lâu dài (hoặc __int64), bạn nên sử dụng% I64d:

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

37

Đó là bởi vì% llu không hoạt động chính xác trong Windows và% d không thể xử lý các số nguyên 64 bit. Tôi đề nghị sử dụng PRIu64 thay vào đó và bạn cũng sẽ thấy nó có thể mang theo Linux.

Hãy thử điều này thay thế:

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

Đầu ra

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

+1 cho tham chiếu đến PRIu64, điều mà tôi chưa từng thấy, nhưng điều này dường như không thể chuyển sang Linux 64 bit (ít nhất) vì PRIu64 mở rộng thành "lu" thay vì "llu".
BD tại Rive dốc

8
Và tại sao điều đó sẽ xấu? Một giá trị dài là 64 bit trên Linux 64 bit, như trên mọi HĐH khác ngoại trừ Windows.
Đổ chuông

@BDatRivenhill Linux / Unix sử dụng LP64 trong đó dài 64 bit
phuclv

1
tuy nhiên, để làm cho nó dễ mang theo hơn, int64_tthay vào đó hãy sử dụng vì có thể có một số triển khai với chiều dài dài lớn hơn dài
phuclv

cái này nên lên đỉnh! - một cập nhật nhỏ: lỗi: hậu tố không hợp lệ trên chữ; C ++ 11 yêu cầu một khoảng cách giữa nghĩa đen và mã định danh [-Wreserved-user-định nghĩa-chữ]
tofutim

14

Trong Linux, nó là %lluvà trong Windows.%I64u

Mặc dù tôi đã tìm thấy nó không hoạt động trong Windows 2000, nhưng dường như có một lỗi ở đó!


với các cửa sổ, (hoặc ít nhất, với trình biên dịch microsoft C cho các cửa sổ) cũng có% I64d,% I32u và% I32d
JustJeff

1
Nó có liên quan gì với Windows 2000? Thư viện C là thư viện xử lý printf.
CMircea

1
Chỉ là những gì tôi quan sát. Tôi đã viết một ứng dụng sử dụng cấu trúc này và nó hoạt động hoàn hảo trên WinXP nhưng lại nhổ rác trên Win2k. Có lẽ đó là một cái gì đó để làm với một cuộc gọi hệ thống mà thư viện C đang tạo ra kernel, có thể đó là một cái gì đó để làm với Unicode, ai biết được. Tôi nhớ phải làm việc xung quanh nó bằng cách sử dụng _i64tot () hoặc một cái gì đó tương tự.
Adam Pierce

7
Âm thanh như MS thực hiện "tự do đổi mới" một lần nữa ... ;-)
Dronz

Sự cố Win2k / Win9x có thể là do unsigned long longkiểu dữ liệu còn khá mới (vào thời điểm đó, với tiêu chuẩn C99) nhưng trình biên dịch C (bao gồm MinGW / GCC) sử dụng thời gian chạy Microsoft C cũ chỉ hỗ trợ thông số C89. Tôi chỉ có quyền truy cập vào các tài liệu API Windows thực sự cũ và hợp lý gần đây. Vì vậy, thật khó để nói chính xác khi nào I64uhỗ trợ được đưa vào. Nhưng nghe có vẻ như thời XP.
veganaiZe

8

Biên dịch nó thành x64 với VS2005:

% llu hoạt động tốt.


3

Ngoài những gì mọi người đã viết cách đây nhiều năm:

  • bạn có thể gặp lỗi này trên gcc / mingw:

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

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

Sau đó, phiên bản mingw của bạn không mặc định là c99. Thêm cờ trình biên dịch này : -std=c99.


3

Rõ ràng không ai tìm ra giải pháp đa nền tảng * trong hơn một thập kỷ kể từ [năm] năm 2008, vì vậy tôi sẽ nối thêm. Xin vui lòng. (Đùa thôi. Tôi không quan tâm.)

Giải pháp: lltoa()

Cách sử dụng:

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

Ví dụ của 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;
}

Không giống như %lldchuỗi định dạng in, chuỗi này hoạt động với tôi dưới GCC 32 bit trên Windows.

*) Vâng, gần như đa nền tảng. Trong MSVC, rõ ràng bạn cần _ui64toa()thay vì lltoa().


1
Tôi không có lltoa.
Antti Haapala

1

Những thứ không chuẩn luôn lạ lùng :)

đối với phần dài dài dưới GNU L, llhoặcq

và dưới cửa sổ tôi tin rằng nó llchỉ


1

Lục giác:

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

Đầu ra:

64bit: FFFFFFFFFFFFFFFF

Rất đẹp! tôi đã tự hỏi làm thế nào tôi có thể có được nó trong đại diện hex
0xAK

Nhưng, hầu hết tất cả các trình biên dịch C ++ và C đều đưa ra cảnh báo: cảnh báo: sử dụng công cụ sửa đổi độ dài 'll' với ký tự loại 'p' [-Wformat =]
Seshadri R

2
câu trả lời hoàn toàn bị phá vỡ này có hành vi gấp đôi không xác định và thậm chí không bắt đầu trả lời câu hỏi .
Antti Haapala

@AnttiHaapala Bạn nói rằng câu trả lời này hoàn toàn bị phá vỡ với hành vi gấp đôi không xác định, bạn có thể giải thích hay tôi sẽ xóa nó? Hoặc giữ nó như một ví dụ xấu tốt?
lama12345

0

Chà, có một cách là biên dịch nó thành x64 với VS2008

Điều này chạy như bạn mong đợi:

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

Đối với mã 32 bit, chúng ta cần sử dụng bộ xác định định dạng __int64 chính xác% I64u. Vì vậy, nó trở thành.

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

Mã này hoạt động cho cả trình biên dịch VS 32 và 64 bit.


Hãy thử một số 64 bit thực tế thay vì '285212672' và tôi không tin ví dụ đầu tiên chạy chính xác, được biên dịch cho bất kỳ mục tiêu nào.
dyasta
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.