Off_t ve size_t gibi türleri nasıl yazdırmalıyım?


148

Ben gibi türlerini yazdırmak çalışıyorum off_tve size_t. printf() Taşınabilir olan için doğru yer tutucu nedir ?

Yoksa bu değişkenleri yazdırmanın tamamen farklı bir yolu var mı?


2
@devin: kullanırken ben bu tür buIdum fopen, fseekvb Mac OS X'te off_tofset için kullanılır.
Georg Schölly

Yanıtlar:


112

Sen kullanabilirsiniz zsize_t ve tbenzeri ifadesi ptrdiff_t için

printf("%zu %td", size, ptrdiff);

Ama benim sayfam bazı eski kütüphanelerinkinden farklı bir karakter zkullandığını ve kullanılmasını caydırdığını söylüyor . Bununla birlikte, standartlaştırılmıştır (C99 standardına göre). Olanlar için intmax_tve int8_tbir stdint.hbaşka cevabı dediğim gibi ve benzeri kullanabileceğiniz makrolar vardır:

printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);

Bunlar sayfalarında listelenmiştir inttypes.h.

Şahsen ben sadece değerleri başka bir yanıt tavsiye gibi unsigned longya da longistiyorum. Eğer, o zaman (ve reddedilmesi gereken, tabii ki) döküm için C99 kullanıyorsanız unsigned long longveya long longve kullanımı %lluveya %lldsırasıyla biçimleri.


2
off_t aslında benim sistemimde uzun bir imzalı.
Georg Schölly

2
Bence man sayfası libc5 tarafından kullanılan Z'nin (büyük harf) kullanımını engelliyor. Z'yi (küçük harf) caydırıyor gibi görünmüyor.
Draemon

12
Kullanılması %zdbir ile size_tolan tanımsız davranış nedeniyle signedness uyumsuzluğu (C99 7.19.6.1 # 9) için. Öyle olmalı %zu.
Jens

7
Peki off_t nasıl yazdırılır?
JohnyTex

3
Ben nasıl görmüyorum @Jens %zdbir ile size_to paragraftan ya da başka gelen tanımsız davranış olur. Aslında, tanımı %ziçinde 7. açıkça tanır %dile size_tve ilgili imzalanan türü ve değeri geçerli bir negatif olmayan bir değerdir uzun olduğunca §6.2.5 9. açıkça karşılık gelen işaretli tür beklenen imzasız türleri değerlerini kullanarak verir imzalı tip.
Chortos-2

108

Yazdırmak için off_t:

printf("%jd\n", (intmax_t)x);

Yazdırmak için size_t:

printf("%zu\n", x);

Yazdırmak için ssize_t:

printf("%zd\n", x);

C99 standardında 7.19.6.1/7 veya biçimlendirme kodlarının daha uygun POSIX belgelerine bakın:

http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html

Uygulamanız bu biçimlendirme kodlarını desteklemiyorsa (örneğin C89'da olduğunuz için), AFAIK'te biraz sorun yaşarsınız, çünkü C89'da biçimlendirme kodlarına sahip ve büyük olması garanti edilen tamsayı türleri yoktur bu tür olarak. Yani uygulamaya özel bir şey yapmanız gerekiyor.

Örneğin, derleyiciniz long longve standart kitaplığınız destekliyorsa %lld, bunun yerine hizmet vermesini bekleyebilirsiniz intmax_t. Ama eğer yapmazsa, geri dönmeniz gerekir long, bu da diğer bazı uygulamalarda başarısız olur, çünkü çok küçüktür.


3
Bu çok daha iyi cevap, imzasız size_t için% zu kullanmayı unutmuş olurdum. Ve intmax_t 'a döküm herhangi bir platformda off_t olan her şey için harika bir çözümdür.
Peter Cordes

2
POSIX ssize_t, aynı boyutta olduğunu garanti etmez size_t, bu nedenle gerçekten taşınabilir kod intmax_t, %jdtıpkı gibi dönüştürülmeli ve yazdırılmalıdır off_t.
nwellnhof

off_t boyutu uzun uzun olabilir ve tanımlarına bağlı olarak değişken olabilir ... Visual Studio bu aynı zamanda uyarır C4477: '_snprintf_s': biçim dizesi '% jd' '__int64' türünde bir argüman gerektirir, ancak varyasyon argümanı 1 'off_t' "yazıyor ... Gerçekten taşınabilir bir yol printf ("% lld \ n ", (uzun uzun) x);
ericcurtin

5

Microsoft için cevap farklı. VS2013 büyük ölçüde C99 uyumludur ancak "[h] he hh, j, z ve t uzunluk önekleri desteklenmez." Size_t "için, 32 bit platformlarda işaretsiz __int32, 64 bit platformlarda işaretsiz __int64" için o, u, x veya X tür belirteciyle I öneki (büyük göz) kullanın. Bkz. VS2013 Boyut belirtimi

Off_t için ise, VC \ include \ sys \ types.h dosyasında uzun olarak tanımlanmıştır.


Bu off_ther zaman long32 bit (64 bit Windows bile 32 bit kullanır long) yaparsa unutmayın .
sourcejedi

3

Hangi C sürümünü kullanıyorsunuz?

C90'da standart uygulama, uygun olduğu şekilde, imzalı veya imzasız uzun süre kullanmak ve buna göre yazdırmaktır. Size_t için% z gördüm, ancak Harbison ve Steele printf () altında bahsetmiyorlar ve her durumda ptrdiff_t veya herhangi bir şekilde size yardımcı olmaz.

C99'da, çeşitli _t türleri kendi printf makrolarıyla birlikte gelir, bu yüzden "Size is " FOO " bytes." ayrıntıları bilmiyorum gibi bir şey , ancak bu oldukça büyük bir sayısal format dosya içerir.


3

İnttypes.h dosyasından biçimlendirme makrolarını kullanmak isteyeceksiniz.

Şu soruya bakın: size_t?


Off_t'ın ptrdiff_t gibi işaretli, işaretçi büyüklüğünde bir int (tam tanımın ne olduğunu bilmiyorum) olduğunu varsayarak PRIdPTR veya PRIiPTR kullanırsınız.
Michael Burr

11
off_tTipi (en 32 bit sistemler bu gün olan) büyük dosyaları destekleyen herhangi 32-bit sistemde bir işaretçi daha büyüktür.
Dietrich Epp

1
@DietrichEpp: Aslında bundan daha kötü; birçok 32 bit sistemde hem off_t hem de off64_t vardır ve off_t makrolarına bağlı olarak aslında off64_t anlamına gelebilir.
SamB

1

Baktığımızda man 3 printfLinux, OS X ve tüm gösteri için destek OpenBSD'de %ziçin size_tve %tiçin ptrdiff_t(C99 için), ancak bu söz hiçbiri off_t. Vahşi Öneriler genelde sunuyoruz %uiçin dönüşüm off_t"doğru yeterince" bildiğim kadarıyla (her ikisi de söyleyebilir gibidir, unsigned intve off_t64-bit ve 32-bit sistemler arasında aynı değişir).


1
Sistemimde (OS X) 32 bit unsigned intve 64 bit var off_t. Böylece oyuncular verilerin kaybolmasına neden olur.
Dietrich Epp

-3

Bu yazıyı en az iki kez gördüm, çünkü kabul edilen cevabı hatırlamak zor (nadiren kullanıyorum zveya jbayraklar ve platformdan bağımsız görünmüyorlar ).

Standart açıkça tam veri uzunluğu demez size_tben ilk uzunluğunu kontrol etmelidir önermek böylece, size_tdaha sonra bunlardan birini seçmek sizin platformda:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

Ve stdinttutarlılık için ham veri türleri yerine türleri kullanmanızı öneririm .


1
C99 ve C11 için standart, değerleri %zuyazdırmak için kullanılabileceğini açıkça belirtir size_t. Bu türlerin uyumlu olduğuna dair bir garanti olmadığından , kesinlikle bir uint32_t/ uint64_tformat belirteci kullanmak için başvurmamalıdır size_t.
otistik

-4

Hatırladığım gibi, bunu yapmanın tek taşınabilir yolu sonucu "unsigned long int" ve kullanımı için kullanmaktır %lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));

1
Uzunluk değiştiricisinin dönüşümden önce gelmesi gerektiği için "% lu" olmalıdır.
dwc

1
örneğin off_t uzun bir imzalı.
Georg Schölly

@ GeorgSchölly - O zaman bir muamma vurdunuz, çünkü long longC ++ standardında mevcut değil ve bu nedenle doğası gereği taşınabilir değildir.
James Curran

-9

off_t için "% zo" kullanın. (sekizli) veya "% zu" olarak girin.


Dosyanın neden sekizli olarak kaydırılmasını istiyorsunuz?
poolie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.