Penentu format size_t platform independen di c?

86

Saya ingin mencetak variabel bertipe size_tC tetapi tampaknya size_tvariabel tersebut memiliki alias berbeda pada arsitektur yang berbeda. Misalnya, pada satu mesin (64-bit), kode berikut tidak menampilkan peringatan apa pun:

tetapi di komputer saya yang lain (32-bit), kode di atas menghasilkan pesan peringatan berikut:

peringatan: format '% ld' mengharapkan tipe 'long int *', tetapi argumen 3 memiliki tipe 'size_t *'

Saya menduga hal ini disebabkan oleh perbedaan ukuran penunjuk, sehingga pada mesin 64-bit saya di- size_talias dengan a long int( "%ld"), sedangkan pada mesin 32-bit saya di- size_talias ke tipe lain.

Apakah ada penentu format khusus untuk size_t?

Ethan Heilman
sumber
1
Pesan peringatan Anda tidak cocok dengan kode. Peringatan itu menyebutkan petunjuk, kode Anda tidak memilikinya. Apakah Anda menghapus beberapa di &suatu tempat?
Jens
Pointer? Tidak, saya tidak mendapatkan peringatan apa pun tentang pointer, sebenarnya tergantung pada mesin apa saya menjalankan kode itu terkadang saya tidak mendapatkan peringatan sama sekali. Coba kode tes berikut: #include <stdio.h> int main () {size_t size = 1; printf ("ukurannya% ld", ukuran); kembali 0; }
Ethan Heilman
1
@EthanHeilman Dia mengacu pada fakta bahwa peringatan Anda mengatakan warning: format '%ld' expects type 'long int *', but argument 3 has type 'size_t *'kapan seharusnya dikatakan warning: format '%ld' expects type 'long int', but argument 3 has type 'size_t'. Apakah Anda mungkin menggunakan scanf()sebagai gantinya saat mendapat peringatan ini?
RastaJedi

Jawaban:

123

Ya: gunakan zpengubah panjang:

Pengubah panjang lain yang tersedia adalah hh(untuk char), h(untuk short), l(untuk long), ll(untuk long long), j(untuk intmax_t), t(untuk ptrdiff_t), dan L(untuk long double). Lihat §7.19.6.1 (7) dari standar C99.

Adam Rosenfield
sumber
apa perbedaan antara zd dan zu? Saya mendapatkan bahwa zd adalah desimal, tetapi apakah itu ditandatangani, jika demikian bagaimana zd ditandatangani mempengaruhi banyak hal.
Ethan Heilman
1
Itu perbedaan antara a size_tdan an ssize_t; yang terakhir ini jarang digunakan.
Adam Rosenfield
26
Benar, jadi dalam kasus ini, Anda harus menggunakan %zu, karena argumennya tidak ditandatangani.
kafe
Opsi lain yang tersedia dijelaskan di halaman manual printf: linux.die.net/man/3/printf
INS
9
@detly: Tidak, zpengubah panjang bukan bagian dari C89 / C90. Jika Anda membidik kode yang sesuai dengan C89, hal terbaik yang dapat Anda lakukan adalah mentransmisikan ke unsigned longdan menggunakan lpengubah panjang sebagai gantinya, misalnya printf("the size is %lu\n", (unsigned long)size);; mendukung C89 dan sistem dengan size_tlebih besar daripada longyang lebih rumit dan akan membutuhkan penggunaan sejumlah makro praprosesor.
Adam Rosenfield
45

Ya ada. Itu %zu(seperti yang ditentukan dalam ANSI C99).

Perhatikan bahwa size_tunsigned, jadi %ldsalah ganda: pengubah panjang salah dan penentu konversi format salah. Jika Anda bertanya-tanya, %zdadalah untuk ssize_t(yang ditandatangani).

maxschlepzig.dll
sumber
1

MSDN , mengatakan bahwa Visual Studio mendukung awalan "I" untuk kode portabel pada platform 32 dan 64 bit.

Arkantos
sumber
6
Ini khusus MS, yang tidak sesuai standar, jadi ini bukan platform independen
phuclv
@Phucl Memang. Dan jika memang tertulis - seperti yang disarankan oleh jawabannya - 'portabel' itu bahkan lebih buruk daripada yang pernah saya ketahui tentang MS. Bukannya itu akan mengejutkan saya ... Saya bukan orang yang tidak disukai karena seseorang berusaha untuk mencoba dan menjawab sesuatu tetapi tetap saja jawaban ini salah. Ah, saya rasa saya mengerti ide di sini dalam 'portabel'. Harus dikatakan bahwa ini berfungsi untuk 32-bit dan 64-bit. Tapi tentu saja.
Pryftan