Saya mencoba untuk mencetak jenis suka off_t
dan size_t
. Apa placeholder yang benar untuk printf()
itu portabel ?
Atau adakah cara yang sama sekali berbeda untuk mencetak variabel-variabel itu?
Saya mencoba untuk mencetak jenis suka off_t
dan size_t
. Apa placeholder yang benar untuk printf()
itu portabel ?
Atau adakah cara yang sama sekali berbeda untuk mencetak variabel-variabel itu?
Jawaban:
Anda dapat menggunakan z
untuk size_t dan t
untuk ptrdiff_t seperti di
printf("%zu %td", size, ptrdiff);
Tetapi halaman buku saya mengatakan beberapa perpustakaan yang lebih tua menggunakan karakter yang berbeda dari z
dan tidak mendukungnya. Namun demikian, itu standar (dengan standar C99). Bagi mereka intmax_t
dan int8_t
dari stdint.h
dan seterusnya, ada makro yang dapat Anda gunakan, seperti jawaban lain yang dikatakan:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Mereka terdaftar di halaman manual inttypes.h
.
Secara pribadi, saya hanya akan memberikan nilai unsigned long
atau long
menyukai jawaban yang direkomendasikan. Jika Anda menggunakan C99, maka Anda dapat (dan harus, tentu saja) cor untuk unsigned long long
atau long long
dan menggunakan %llu
atau %lld
format masing-masing.
%zd
dengan size_t
adalah perilaku undefined karena signedness mismatch (C99 7.19.6.1 # 9). Pasti begitu %zu
.
%zd
dengan size_t
perilaku yang tidak terdefinisi dari paragraf itu atau dari yang lain. Pada kenyataannya, definisi %z
dalam # 7 secara eksplisit memungkinkan %d
dengan size_t
dan jenis bertanda tangan yang sesuai, dan §6.2.5 # 9 secara eksplisit memungkinkan penggunaan nilai-nilai dari jenis yang tidak ditandatangani di mana jenis yang ditandatangani diharapkan, asalkan nilainya adalah nilai nonnegatif yang valid dari tipe yang ditandatangani.
Untuk mencetak off_t
:
printf("%jd\n", (intmax_t)x);
Untuk mencetak size_t
:
printf("%zu\n", x);
Untuk mencetak ssize_t
:
printf("%zd\n", x);
Lihat 7.19.6.1/7 dalam standar C99, atau dokumentasi POSIX yang lebih mudah tentang kode pemformatan:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Jika implementasi Anda tidak mendukung kode pemformatan tersebut (misalnya karena Anda menggunakan C89), maka Anda memiliki sedikit masalah karena AFAIK tidak ada tipe integer di C89 yang memiliki kode pemformatan dan dijamin sebesar sebagai tipe ini. Jadi, Anda perlu melakukan sesuatu yang spesifik implementasi.
Misalnya jika kompiler Anda memiliki long long
dan pustaka standar Anda mendukung %lld
, Anda dapat dengan yakin mengharapkan yang akan menggantikannya intmax_t
. Tetapi jika tidak, Anda harus kembali ke long
, yang akan gagal pada beberapa implementasi lain karena terlalu kecil.
ssize_t
memiliki ukuran yang sama size_t
, jadi kode yang benar-benar portabel harus mengubahnya menjadi intmax_t
dan mencetak %jd
seperti off_t
.
Untuk Microsoft, jawabannya berbeda. VS2013 sebagian besar memenuhi persyaratan C99 tetapi "[t] heh, j, z, dan t panjang prefix tidak didukung." Untuk size_t "yaitu, unsigned __int32 pada platform 32-bit, unsigned __int64 pada platform 64-bit" gunakan awalan I (modal mata) dengan specifier tipe o, u, x, atau X. Lihat spesifikasi ukuran VS2013
Sedangkan untuk off_t, ini didefinisikan sebagai panjang dalam VC \ include \ sys \ types.h.
off_t
selalu long
itu akan membuatnya 32-bit (bahkan 64-bit Windows menggunakan 32-bit untuk long
).
Versi C mana yang Anda gunakan?
Di C90, praktik standar adalah menggunakan untuk ditandatangani atau tidak ditandatangani lama, yang sesuai, dan cetak sesuai. Saya telah melihat% z untuk size_t, tetapi Harbison dan Steele tidak menyebutkannya di bawah printf (), dan dalam hal apa pun itu tidak akan membantu Anda dengan ptrdiff_t atau apa pun.
Di C99, berbagai jenis _t datang dengan makro printf mereka sendiri, jadi sesuatu seperti "Size is " FOO " bytes."
saya tidak tahu detailnya, tapi itu bagian dari format numerik yang cukup besar termasuk file.
Anda ingin menggunakan makro pemformatan dari inttypes.h.
Lihat pertanyaan ini: String format platform silang untuk variabel tipe size_t?
off_t
jenis lebih besar dari pointer pada sistem 32-bit yang mendukung file besar (yang paling 32-bit sistem hari ini).
Melihat di man 3 printf
Linux, OS X, dan OpenBSD semuanya menunjukkan dukungan %z
untuk size_t
dan %t
untuk ptrdiff_t
(untuk C99), tetapi tidak satupun yang menyebutkan off_t
. Saran di alam liar biasanya menawarkan %u
konversi off_t
, yang "cukup benar" sejauh yang saya tahu (keduanya unsigned int
dan off_t
bervariasi secara identik antara sistem 64-bit dan 32-bit).
unsigned int
dan 64-bit off_t
. Jadi para pemain akan menyebabkan data menjadi hilang.
Saya melihat posting ini setidaknya dua kali, karena jawaban yang diterima sulit untuk diingat bagi saya (saya jarang menggunakan z
atau j
menandai dan mereka tampaknya bukan platform independen ).
The standar tidak pernah mengatakan secara jelas panjang data yang tepat dari size_t
, jadi saya sarankan pertama Anda harus memeriksa panjang size_t
pada platform Anda kemudian pilih salah satu dari mereka:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
Dan saya sarankan menggunakan stdint
tipe daripada tipe data mentah untuk konsistensi.
%zu
dapat digunakan untuk mencetak size_t
nilai. Satu harus pasti tidak resor untuk menggunakan uint32_t
/ uint64_t
format yang specifier untuk mencetak size_t
, karena tidak ada jaminan bahwa jenis-jenis yang kompatibel.
Seingat saya, satu-satunya cara portabel untuk melakukannya, adalah membuang hasilnya ke "unsigned long int" dan gunakan %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
tidak ada dalam standar C ++, dan dengan demikian bersifat non-portabel.
fopen
,fseek
, dll di Mac OS X.off_t
digunakan untuk offset.