uint32_t ve size_t için printf biçim belirticileri


101

Şunlara sahibim

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

Derlerken şu uyarıyı alıyorum:

format ‘%lu expects type long unsigned int’, but argument has type uint32_t

Bunu splint kullanarak çalıştırdığımda aşağıdakileri elde ettim:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Herhangi bir tavsiye için çok teşekkürler,


2
C89 desteklemediği uint32_tgelen <stdint.h>veya <inttypes.h>; Bu türleri kullanmak istiyorsanız, C89'a yükseltmelisiniz. Bir uzantı olarak, GCC'nin bunları kullanmanıza izin vermesi muhtemeldir, ancak C89'un böyle bir desteği yoktu.
Jonathan Leffler

11
Ve için resmi C99 biçim değiştiricisi size_t, ' z'dir "%zu".
Jonathan Leffler


@ Kenny'nin cevabının en iyisi olduğuna inanıyorum uint32_t, ancak eksik size_t. @ u0b34a0f6ae'nin yanıtı her ikisini de içerir.
jww

Jonathan Leffler'ın tarafından 1 yorumunda C89 2. söz C99 olmalıdır
bph

Yanıtlar:


28

Aslında bir (32 bit) olduğunda (muhtemelen 64 bit) ile size_taynı olmasını bekliyormuşsunuz gibi geliyor . Her iki durumda da kullanmayı deneyin .unsigned longunsigned int%zu

Yine de tam olarak emin değilim.


1
Derleme sırasında uyarı yok. Bununla birlikte, splint çalıştırırken aşağıdakileri alıyorum: 1) printf (% u) işaretsiz int'in uint32_t almasını bekliyor: i 2) printf (% u) unsigned
int'in

Sanki splint sadece bilgiçlik yapıyormuş gibi geliyor. Muhtemelen kaynak koddaki türlerin adlarını değiştiriyor ve eşdeğer olduklarının farkında değil. @ KennyTM'nin cevabıyla ne yapacağını merak ediyorum ... Kesinlikle daha taşınabilir olmalı.
Cogwheel

3
splint aslında doğru olanı yapıyor. Çünkü int32_tolur intderleyici üzerinde / platform o olmayabilir anlamına gelmez longdiğerinde. Aynı size_t. Aslında yolunun dışına çıkıyor ve bu taşınabilirlik hatasını tespit etmek için daha fazla çalışma yapıyor çünkü kolay, doğal kontrol, derleyicinin yaptığı gibi typedef'i onurlandırmak olacaktır.
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

4
-1, maalesef taşınabilir değil. Gereken tek şey, biçim belirleyicilerinin ve türlerin aynı fikirde olması ve bunu doğru yapmak için her zaman dönüştürme yapabilmenizdir. uzun en az 32 bittir, bu nedenle ile %lubirlikte (unsigned long)kher zaman doğrudur. size_tdaha karmaşıktır, bu yüzden %zuC99'a eklenmiştir. Bunu kullanamıyorsanız, o zaman ona aynı şekilde davranın k( longC89'daki en büyük türdür, size_tdaha büyük olması pek olası değildir).
u0b34a0f6ae

140

Deneyin

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

zİle aynı uzunlukta bir tamsayıyı temsil eder size_t, ve PRIu32makro C99 başlığında tarifinttypes.h , işaretsiz 32 bit tam sayıyı temsil eder.


3
@robUK: Heh. Splint için bir hata dosyalamanızı öneririm.
kennytm

8
Bu doğru cevap. Kişisel tavsiyem basitçe döküm yapmak olsa da, örneğin printf( "%lu", (unsigned long )i ). Aksi takdirde, bir tür değişikliği nedeniyle kodun her yerinde bir yığın uyarı ile sonuçlanır.
Dummy00001

1
Bu doğru cevap. Splint için bir hata bildirme konusunda KennyTM'ye katılıyorum. Bu arada, "% zu" size_t için uygun formattır. Size_t yazdırmak için PRI * makrolarından herhangi birine ihtiyacınız yoktur.
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

1
Doğru hatırlıyorsam% zu C99'dur ve soruda 'C89' yazdı.
alcor

8
@alcor evet C89 koydu (görünüşe göre kullandığı gcc derleyici bayrağı) ama kullanıyor uint32_tbu yüzden aslında C99 kodu ve bu şekilde derlenmesi gerekiyor.
Colin D Bennett

28

Gereken tek şey, biçim belirleyicilerinin ve türlerin aynı fikirde olması ve bunu doğru yapmak için her zaman dönüştürme yapabilmenizdir. longen az 32 bittir, bu nedenle ile %lubirlikte (unsigned long)kher zaman doğrudur:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_tdaha karmaşıktır, bu yüzden %zuC99'a eklenmiştir. Bunu kullanamıyorsanız, o zaman ona aynı şekilde davranın k( longC89'daki en büyük türdür, size_tdaha büyük olması pek olası değildir).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Biçim tanımlayıcılarını ilettiğiniz tür için doğru alamazsanız printf, diziden çok fazla veya çok az bellek okumakla eşdeğerdir. Türleri eşleştirmek için açık yayınlar kullandığınız sürece, taşınabilir.


17

PRI * makrolarını kullanmak istemiyorsanız, HERHANGİ bir tamsayı türünü yazdırmak için başka bir yaklaşım , sırasıyla intmax_tveya uintmax_tve "%jd"veya kullanmaktır %ju. Bu, örneğin PRI * makroları tanımlanmamış POSIX (veya diğer işletim sistemi) türleri için özellikle yararlıdır off_t.

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.