mã định dạng printf cho uint32_t và size_t


101

Tôi có cái sau

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

Tôi nhận được cảnh báo sau khi biên dịch:

format ‘%lu expects type long unsigned int’, but argument has type uint32_t

Khi tôi chạy điều này bằng cách sử dụng nẹp, tôi nhận được những điều sau:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Cảm ơn rât nhiêu vi lơi khuyên,


2
C89 không hỗ trợ uint32_ttừ <stdint.h>hoặc <inttypes.h>; nếu bạn muốn sử dụng những loại đó, bạn nên nâng cấp lên C89. Là một phần mở rộng, có khả năng GCC cho phép bạn sử dụng chúng, nhưng C89 không có bất kỳ hỗ trợ nào như vậy.
Jonathan Leffler

10
Và công cụ sửa đổi định dạng C99 chính thức cho size_tlà 'z', như trong "%zu".
Jonathan Leffler


Tôi tin rằng câu trả lời của @ kenny là tốt nhất uint32_t, nhưng nó thiếu size_t. Câu trả lời của @ u0b34a0f6ae bao gồm cả hai.
jww

Đề cập đến lần thứ 2 của C89 trong bình luận của 1st bởi Jonathan Leffler nên C99
bph

Câu trả lời:


28

Có vẻ như bạn đang mong đợi size_tgiống unsigned long(có thể là 64 bit) trong khi nó thực sự là unsigned int(32 bit). Hãy thử sử dụng %zutrong cả hai trường hợp.

Tôi không hoàn toàn chắc chắn.


1
Không có cảnh báo khi biên dịch. Tuy nhiên, chạy nẹp tôi nhận được như sau: 1) printf (% u) hy vọng unsigned int được uint32_t: i 2) printf (% u) hy vọng unsigned int được size_t: k
ant2009

Vậy thì nghe có vẻ như nẹp chỉ là một thứ gì đó khổng lồ. Nó có thể viết tắt tên của các loại trong mã nguồn và không nhận ra chúng tương đương nhau. Tôi tự hỏi nó sẽ làm gì với câu trả lời của @ KennyTM ... Nó chắc chắn phải di động hơn.
Cogwheel

3
nẹp thực sự đang làm điều đúng đắn. Chỉ vì nó int32_txảy ra inttrên trình biên dịch / nền tảng của bạn không có nghĩa là nó có thể không longở trên nền tảng khác. Tương tự cho size_t. Nó thực sự đang đi đúng hướng và phải làm nhiều việc hơn để phát hiện lỗi di động này vì việc kiểm tra tự nhiên, dễ dàng sẽ chỉ là tôn vinh typedef giống như trình biên dịch.
R .. GitHub DỪNG TRỢ GIÚP NGAY LÚC NÀY

4
-1, xin lỗi nó không di động được. Tất cả những gì cần thiết là các chỉ định định dạng và các loại đồng ý và bạn luôn có thể truyền để biến điều đó thành sự thật. dài ít nhất là 32bits, vì vậy %lucùng với (unsigned long)kluôn đúng. size_tphức tạp hơn, đó là lý do tại sao %zuđược thêm vào trong C99. Nếu bạn không thể sử dụng nó, thì hãy xử lý nó giống như k( longlà loại lớn nhất trong C89, size_trất khó có thể lớn hơn).
u0b34a0f6ae

139

Thử

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

Đại zdiện cho một số nguyên có độ dài bằng size_tPRIu32macro, được xác định trong tiêu đề C99inttypes.h , đại diện cho một số nguyên 32 bit không dấu.


3
@robUK: Hì. Tôi đề nghị bạn gửi một lỗi cho nẹp.
kennytm

8
Đây là câu trả lời đúng. Mặc dù khuyến nghị cá nhân của tôi là chỉ cần truyền, ví dụ printf( "%lu", (unsigned long )i ). Nếu không thì sau này sẽ có hàng đống cảnh báo trên toàn bộ mã do thay đổi kiểu.
Dummy00001,

1
Đây là câu trả lời chính xác. Tôi đồng ý với KennyTM về việc sửa lỗi cho nẹp. Nhân tiện, "% zu" là định dạng thích hợp cho size_t. Bạn không cần bất kỳ macro PRI * nào để in size_t.
R .. GitHub DỪNG TRỢ GIÚP NGAY LÚC NÀY

1
Nếu tôi nhớ không nhầm thì% zu là C99, và trong câu hỏi anh ấy viết 'C89'.
alcor

8
@alcor vâng anh ấy đã đặt C89 (rõ ràng là cờ trình biên dịch gcc mà anh ấy đang sử dụng) nhưng anh ấy đang sử dụng uint32_tvì vậy thực tế nó là mã C99 và nên được biên dịch như vậy.
Colin D Bennett

28

Tất cả những gì cần thiết là các chỉ định định dạng và các loại đồng ý và bạn luôn có thể truyền để biến điều đó thành sự thật. longít nhất là 32 bit, vì vậy %lucùng với (unsigned long)kluôn đúng:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_tphức tạp hơn, đó là lý do tại sao %zuđược thêm vào trong C99. Nếu bạn không thể sử dụng nó, thì hãy xử lý nó giống như k( longlà loại lớn nhất trong C89, size_trất khó có thể lớn hơn).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Nếu bạn không nhận được các chỉ định định dạng chính xác cho kiểu bạn đang truyền, thì printfviệc đọc quá nhiều hoặc quá ít bộ nhớ ra khỏi mảng sẽ tương đương với việc đọc. Miễn là bạn sử dụng phôi rõ ràng để khớp các loại, nó có thể di động.


17

Nếu bạn không muốn sử dụng các macro PRI *, một cách tiếp cận khác để in BẤT KỲ loại số nguyên nào là truyền tới intmax_thoặc uintmax_tvà sử dụng "%jd"hoặc %ju, tương ứng. Điều này đặc biệt hữu ích cho các loại POSIX (hoặc hệ điều hành khác) không có macro PRI * được xác định, chẳng hạn off_t.

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.