2010-07-02 32 views
81

Tôi đã sauđịnh dạng printf specifiers cho uint32_t và size_t

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 này bằng nẹp tôi đã nhận như sau:

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

Rất cám ơn mọi lời khuyên,

+1

C89 không hỗ trợ 'uint32_t' từ' 'hoặc' '; nếu bạn muốn sử dụng các 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ỳ sự hỗ trợ nào như vậy. –

+9

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

+1

http://stackoverflow.com/questions/1401526/how-to-use-printf-to-display-off-t-nlink-t-size-t-and-other-special-types –

Trả lời

18

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

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

+1

Không có cảnh báo khi biên dịch.Tuy nhiên, chạy splint tôi nhận được những điều sau đây: 1) printf (% u) dự kiến ​​int unsigned được uint32_t: i 2) printf (% u) dự kiến ​​int unsigned được size_t: k – ant2009

+0

Âm thanh như nẹp chỉ là pedantic, sau đó. Nó có lẽ sẽ 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 ... Chắc chắn nó sẽ dễ dàng hơn. – Cogwheel

+3

nẹp là thực sự làm điều đúng. Chỉ vì 'int32_t' xảy ra là' int' trê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 phải là 'long' trên một trình duyệt khác. Tương tự cho 'size_t'. Nó thực sự đi ra khỏi con đường của nó và làm ** hơn ** công việc để phát hiện lỗi này portability kể từ khi kiểm tra dễ dàng, tự nhiên sẽ chỉ để tôn vinh typedef như trình biên dịch nào. –

114

Hãy thử

#include <inttypes.h> 
... 

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

Các z đại diện cho một số nguyên có độ dài tương tự như size_t, và PRIu32 vĩ mô, defined in the C99 header inttypes.h, đại diện cho một số nguyên 32-bit unsigned.

+0

Biên dịch không có cảnh báo. Nhưng nẹp không thích nó. Mã định dạng không được công nhận:% zu. Và thứ hai. Lỗi phân tích cú pháp. (Để được trợ giúp về lỗi phân tích cú pháp, hãy xem nẹp trợ giúp phân tích cú pháp.) *** Không thể tiếp tục. – ant2009

+3

@robUK: Heh. Tôi đề nghị bạn nộp một lỗi cho nẹp. – kennytm

+6

Đây là câu trả lời đúng. Mặc dù đề xuất cá nhân của tôi chỉ đơn giản là diễn xuất, ví dụ: 'printf ("% lu ", (unsigned long) i)'. Nếu không, một kết thúc sau đó với đống cảnh báo trên tất cả các mã do một sự thay đổi loại. – Dummy00001

16

Nếu bạn không muốn sử dụng các macro PRI *, cách tiếp cận khác để in BẤT CỨ kiểu số nguyên là để cast để intmax_t hoặc uintmax_t và 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 các hệ điều hành khác) không được xác định bằng các macro PRI *, ví dụ: off_t.

21

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

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

size_t là phức tạp hơn, đó là lý do %zu đã được bổ sung trong C99. Nếu bạn không thể sử dụng, sau đó xử lý nó giống như k (long là loại lớn nhất trong C89, size_t là rấ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 specifiers định dạng chính xác cho các loại bạn đang đi qua, sau đó printf sẽ làm tương đương với việc đọc bộ nhớ quá nhiều hay quá ít ra khỏi mảng. Miễn là bạn sử dụng phôi rõ ràng để phù hợp với các loại, nó di động.

Các vấn đề liên quan