Tôi đang cố gắng in các loại như off_t
và size_t
. Giữ chỗ chính xác cho printf()
đó là di động là gì?
Hoặc có một cách hoàn toàn khác để in các biến đó?
Tôi đang cố gắng in các loại như off_t
và size_t
. Giữ chỗ chính xác cho printf()
đó là di động là gì?
Hoặc có một cách hoàn toàn khác để in các biến đó?
Câu trả lời:
Bạn có thể sử dụng z
cho size_t và t
cho ptrdiff_t như trong
printf("%zu %td", size, ptrdiff);
Nhưng trang của tôi nói rằng một số thư viện cũ đã sử dụng một ký tự khác z
và không khuyến khích sử dụng nó. Tuy nhiên, nó được chuẩn hóa (theo tiêu chuẩn C99). Đối với những người intmax_t
và int8_t
của stdint.h
và như vậy, có macro bạn có thể sử dụng, như câu trả lời khác nói:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Chúng được liệt kê trong trang của inttypes.h
.
Cá nhân, tôi sẽ chỉ đưa ra các giá trị unsigned long
hoặc long
giống như một câu trả lời khác khuyến nghị. Nếu bạn sử dụng C99, thì dĩ nhiên, bạn có thể (và nên) chuyển sang unsigned long long
hoặc long long
và sử dụng các định dạng %llu
hoặc %lld
định dạng tương ứng.
%zd
với a size_t
là hành vi không xác định do sự không phù hợp về chữ ký (C99 7.19.6.1 # 9). Nó phải như vậy %zu
.
%zd
với một size_t
hành vi không xác định từ đoạn đó hoặc từ bất kỳ khác. Trong thực tế, định nghĩa của %z
# 7 cho phép rõ ràng %d
với size_t
và loại đã ký tương ứng và §6.2.5 # 9 cho phép sử dụng rõ ràng các giá trị của các loại không dấu trong đó loại được ký tương ứng được dự kiến, miễn là giá trị là giá trị không âm hợp lệ của loại đã ký.
Để in off_t
:
printf("%jd\n", (intmax_t)x);
Để in size_t
:
printf("%zu\n", x);
Để in ssize_t
:
printf("%zd\n", x);
Xem 7.19.6.1/7 trong tiêu chuẩn C99 hoặc tài liệu mã định dạng POSIX thuận tiện hơn:
http://pub.opengroup.org/onlinepub/009695399/fifts/fprintf.html
Nếu việc triển khai của bạn không hỗ trợ các mã định dạng đó (ví dụ vì bạn đang sử dụng C89), thì bạn có một chút vấn đề vì AFAIK không có loại số nguyên trong C89 có mã định dạng và được đảm bảo là lớn như những loại này. Vì vậy, bạn cần phải làm một cái gì đó cụ thể thực hiện.
Ví dụ: nếu trình biên dịch của bạn có long long
và thư viện chuẩn của bạn hỗ trợ %lld
, bạn có thể tự tin mong đợi rằng nó sẽ phục vụ thay thế intmax_t
. Nhưng nếu không, bạn sẽ phải quay lại long
, điều này sẽ thất bại đối với một số triển khai khác vì nó quá nhỏ.
ssize_t
có cùng kích thước size_t
, vì vậy mã thực sự di động nên chuyển đổi nó thành intmax_t
và in %jd
giống như vậy off_t
.
Đối với Microsoft, câu trả lời là khác nhau. VS2013 phần lớn tuân thủ C99 nhưng "[t] he hh, j, z và t tiền tố không được hỗ trợ." Đối với size_t "nghĩa là, không dấu __int32 trên nền tảng 32 bit, không dấu __int64 trên nền tảng 64 bit" sử dụng tiền tố I (con mắt vốn) với công cụ xác định loại o, u, x hoặc X. Xem thông số Kích thước VS2013
Đối với off_t, nó được định nghĩa là dài trong VC \ include \ sys \ type.h.
off_t
luôn luôn long
là nó sẽ làm cho nó 32 bit (thậm chí Windows 64 bit sử dụng 32 bit cho long
).
Bạn đang sử dụng phiên bản nào của C?
Trong C90, thông lệ tiêu chuẩn là chuyển sang ký dài hoặc không dấu, nếu phù hợp và in tương ứng. Tôi đã thấy% z cho size_t, nhưng Harbison và Steele không đề cập đến nó trong printf () và trong mọi trường hợp sẽ không giúp bạn với ptrdiff_t hoặc bất cứ điều gì.
Trong C99, các loại _t khác nhau đi kèm với các macro printf của riêng chúng, vì vậy một số thứ như "Size is " FOO " bytes."
tôi không biết chi tiết, nhưng đó là một phần của định dạng số khá lớn bao gồm tệp.
Bạn sẽ muốn sử dụng các macro định dạng từ inttypes.h.
Xem câu hỏi này: Chuỗi định dạng nền tảng chéo cho các biến loại size_t?
off_t
loại lớn hơn một con trỏ trên bất kỳ hệ thống 32-bit hỗ trợ các file lớn (đó là hầu hết các hệ 32-bit những ngày này).
Nhìn man 3 printf
vào Linux, OS X và OpenBSD đều hiển thị hỗ trợ %z
cho size_t
và %t
choptrdiff_t
(cho C99), nhưng không ai trong số đó đề cập đến off_t
. Các đề xuất trong tự nhiên thường cung cấp %u
chuyển đổi cho off_t
, "đủ chính xác" theo như tôi có thể nói (cả hai unsigned int
và off_t
khác nhau giữa các hệ thống 64 bit và 32 bit).
unsigned int
và 64 bit off_t
. Vì vậy, các diễn viên sẽ làm mất dữ liệu.
Tôi đã thấy bài đăng này ít nhất hai lần, bởi vì câu trả lời được chấp nhận là khó nhớ đối với tôi (tôi hiếm khi sử dụng z
hoặc gắn j
cờ và chúng dường như không độc lập với nền tảng ).
Các tiêu chuẩn không bao giờ nói rõ chiều dài dữ liệu chính xác của size_t
, vì vậy tôi đề nghị đầu tiên bạn nên kiểm tra chiều dài size_t
trên nền tảng của bạn sau đó chọn một trong số họ:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
Và tôi đề nghị sử dụng stdint
các loại thay vì các loại dữ liệu thô cho thống nhất.
%zu
có thể được sử dụng để in size_t
các giá trị. Người ta phải chắc chắn không phải nghỉ mát để sử dụng một uint32_t
/ uint64_t
format specifier in một size_t
, như không có gì bảo đảm rằng những loại tương thích.
Như tôi nhớ, cách di động duy nhất để làm điều đó là sử dụng kết quả thành "unsign long int" và sử dụng %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
không tồn tại trong tiêu chuẩn C ++, và do đó vốn dĩ không thể mang theo được.
fopen
,fseek
vv trên Mac OS X.off_t
được sử dụng để bù đắp.