2012-07-03 19 views
9

aşağıdaki program tanımlanmamış olan davranışı:Neden gcc -Wformat, imzasız bir int üzerinde printf% d hakkında uyarı yapmıyor?

#include <stdio.h> 

int main(void) 
{ 
    unsigned int x = -100; // This is fine, becomes UINT_MAX - 100 
    printf("%d\n", x); // This is undefined behavior. 
    return 0; 
} 

C99 7.19.6.1p8 durumları% d int bağımsız değişken bekliyor.

bildiren 7.19.6.1p9

C99 "bir bağımsız değişken belirteci karşılık gelen için doğru türde değildir, davranış tanımlanmamış olan".

Ancak ( -Wall ile birlikte) gcc -Wformat neden yukarıdaki programda, şikayet olmaz? Bu bir hata mı, yoksa kasıtlı bir ihmal mi? gcc manpage itibaren

:

-Wformat 

kontrol vb "printf" ve "scanf" için, verilen argümanlar belirtilen format dizesine uygun türde olduğundan emin olmak için çağırır ve bu formatta belirtilen dönüşümler dize anlamlıdır

+2

C99 6.3.1.3p3 uygulaması tanımlanır imzalı imzasız dönüşümünü diyor. – jxh

+0

@ user315052: Dönüşüm yok; "x" (bir "imzasız int" nesnesi) temsili, "int" türündeymiş gibi yorumlanır. –

+0

@KeithThompson: C99 7.15.1.1p2, son cümlesi nedeniyle, argüman türlerini "va_arg" makrosuyla dönüştürürken imzalı/imzasız için bir istisna oluşturduğunu düşünüyorum. – jxh

cevap

8

En iyi tahminim, UB'nin yalnızca değeriyle değil, yalnızca türüne göre uyarıldığı için uyarının atlanmasıdır. va_arg, imzanın hem imzalanmış hem de imzasız türde değeri gösterilebildiği sürece uyumsuzluğa izin verir. Ancak, printf ve arkadaşlar va_arg açısından belirtilmemiş ve standart, herhangi bir tür uyumsuzluğunun UB'ye neden olduğunu belirtir, ancak bu muhtemelen standartta bir hatadır. Aksi takdirde, printf("%x",1); UB'yi çağırırdı. konu üzerine sorumu bakınız:

Does printf("%x",1) invoke undefined behavior?

+0

Teşekkürler. Bu, 6.2.5p6 olarak anlamlıdır, aynı miktarda depolama alanı kullanmak için int ve unsigned int gerektirir. İmzasız bir firmada% d printf teknik olarak tanımlanmamış olsa da, bunun gerçek sorunlara neden olması için makul bir sebep yoktur. – Chris

+0

Standart, printf() '' 'kullandığı anlamına gelmez, ancak' printf() 'işlevine bir işaretçi oluşturabiliyor olmanız gerçeği, argüman geçirme mekanizmasında en azından bazı ortaklıkları ifade eder. . –

+3

GCC 5.0 şimdi böyle bir uyarıda bulunuyor: ['-Wformat-signedness'] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60194) (' WWatat' tarafından etkinleştirildi). – cremno