Định dạng size_t độc lập với nền tảng Các chỉ định định dạng trong c?


86

Tôi muốn in ra một biến kiểu size_ttrong C nhưng có vẻ như nó size_tđược đặt biệt danh cho các kiểu biến khác nhau trên các kiến ​​trúc khác nhau. Ví dụ: trên một máy (64-bit), mã sau không đưa ra bất kỳ cảnh báo nào:

size_t size = 1;
printf("the size is %ld", size);

nhưng trên máy khác của tôi (32-bit), mã trên tạo ra thông báo cảnh báo sau:

cảnh báo: định dạng '% ld' mong đợi loại 'long int *', nhưng đối số 3 có loại 'size_t *'

Tôi nghi ngờ điều này là do sự khác biệt về kích thước con trỏ, vì vậy trên máy 64-bit của tôi size_tđược đặt bí danh là long int( "%ld"), trong khi trên máy 32-bit của tôi size_tđược đặt bí danh là một kiểu khác.

Có công cụ định dạng dành riêng cho size_tkhông?


Thông báo cảnh báo của bạn không khớp với mã. Cảnh báo đề cập đến con trỏ, mã của bạn không có bất kỳ. Bạn đã xóa một số &ở đâu đó?
Jens

Con trỏ? Không Tôi không nhận được bất kỳ cảnh báo nào về con trỏ, trên thực tế, tùy thuộc vào máy tôi chạy mã đó trên máy nào, đôi khi tôi không nhận được cảnh báo nào cả. Hãy thử mã kiểm tra sau: #include <stdio.h> int main () {size_t size = 1; printf ("kích thước là% ld", size); trả về 0; }
Ethan Heilman


1
@EthanHeilman Anh ấy đang đề cập đến thực tế là cảnh báo của bạn cho biết warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'khi nào nó có thể nên nói warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'. Bạn có thể sử dụng scanf()thay thế khi nhận được những cảnh báo này không?
RastaJedi

Câu trả lời:


123

Có: sử dụng công cụ zsửa đổi độ dài:

size_t size = sizeof(char);
printf("the size is %zu\n", size);  // decimal size_t ("u" for unsigned)
printf("the size is %zx\n", size);  // hex size_t

Các công cụ sửa đổi độ dài khác có sẵn là hh(for char), h(for short), l(for long), ll(for long long), j(for intmax_t), t(for ptrdiff_t) và L(for long double). Xem §7.19.6.1 (7) của tiêu chuẩn C99.


sự khác biệt giữa zd và zu là gì? Tôi nhận được rằng zd là số thập phân, nhưng nó có được ký không, nếu vậy làm thế nào để zd được ký có hiệu lực.
Ethan Heilman,

1
Đó là sự khác biệt giữa a size_tvà an ssize_t; cái sau hiếm khi được sử dụng.
Adam Rosenfield

26
Đúng, vì vậy trong trường hợp này, bạn nên sử dụng %zu, vì đối số không có dấu.
caf

Các tùy chọn khác có sẵn được giải thích trong trang hướng dẫn printf: linux.die.net/man/3/printf
INS

9
@detly: Không, công cụ zsửa đổi độ dài không phải là một phần của C89 / C90. Nếu bạn đang nhắm đến cho mã C89-tuân thủ, tốt nhất bạn có thể làm được đúc để unsigned longvà sử dụng lsửa đổi lần chiều dài thay vào đó, ví dụ printf("the size is %lu\n", (unsigned long)size);; hỗ trợ cả C89 và các hệ thống size_tlớn hơn longthì phức tạp hơn và sẽ yêu cầu sử dụng một số macro tiền xử lý.
Adam Rosenfield

45

Có, có. Nó là %zu(như được chỉ định trong ANSI C99).

size_t size = 1;
printf("the size is %zu", size);

Lưu ý rằng size_tkhông có dấu, do đó %ldsai kép: công cụ sửa đổi độ dài sai và công cụ chỉ định chuyển đổi định dạng sai. Trong trường hợp bạn thắc mắc, %zdlà cho ssize_t(được ký).


1

MSDN cho biết Visual Studio hỗ trợ tiền tố "I" cho mã di động trên nền tảng 32 và 64 bit.

size_t size = 10;
printf("size is %Iu", size);

6
đó là MS cụ thể, mà không là phù hợp với tiêu chuẩn, vì vậy nó không nền tảng độc lập
phuclv

@phuclv Thật vậy. Và nếu nó thực sự nói - như câu trả lời gợi ý - 'di động' thì nó thậm chí còn tệ hơn tôi từng biết về MS. Không phải điều đó sẽ làm tôi ngạc nhiên ... Tôi không phải là người phản đối vì ai đó đã cố gắng thử và trả lời điều gì đó nhưng câu trả lời này vẫn sai. À, tôi nghĩ tôi hiểu ý tưởng ở đây ở dạng 'di động'. Phải nói rằng nó hoạt động cho cả 32-bit và 64-bit. Nhưng tất nhiên nó sẽ.
Pryftan
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.