2012-07-03 14 views
9

Poniższy program jest niezdefiniowane zachowanie:Dlaczego gcc -Wformat nie ostrzega o printf% d na unsigned int?

#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 stany% d oczekuje int argument.

C99 7.19.6.1p9 stwierdza: „Jeśli argument nie jest prawidłowy typ dla odpowiednią specyfikacją konwersji, zachowanie jest niezdefiniowane ”.

Jednak gcc -Wformat (który jest dołączony -Wall) nie będzie narzekać powyższego programu, dlaczego? Czy to błąd, czy celowe zaniedbanie?

Z podręcznika gcc:

-Wformat 

Sprawdź nazywa się "printf" i "scanf" itp, aby upewnić się, że argumenty przekazane do odpowiednich rodzajów mieć ciąg formacie określonym, a konwersje wymienione w formacie ciąg ma sens

+2

C99 6.3.1.3p3 mówi konwersję unsigned do podpisany jest realizacja zdefiniowane. – jxh

+0

@ user315052: Nie ma konwersji; reprezentacja 'x' (' unsigned int' object) interpretowana jest tak, jakby była typu 'int'. –

+0

@KeithThompson: Myślę, że jest to z powodu C99 7.15.1.1p2, ostatnie zdanie, gdzie robi wyjątek dla podpisanego/unsigned podczas konwersji typów argumentów poprzez makro 'va_arg'. – jxh

Odpowiedz

8

Moim zdaniem domyślnym jest to, że ostrzeżenie jest pomijane, ponieważ UB jest prawdopodobnie wywoływane przez wartość o wartości, a nie tylko przez typ. va_arg umożliwia sygnaturę niezgodności, o ile wartość jest reprezentowalna zarówno dla typu podpisanego, jak i niepodpisanego. Jednakże, printf i przyjaciele nie są określone w kategoriach va_arg, a standard stwierdza, że ​​wszelkie niezgodności typów powodują UB, ale jest to prawdopodobnie błąd w standardzie. W przeciwnym razie, printf("%x",1); może wywołać UB. Zobacz moje pytanie na temat:

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

+0

Dzięki. To ma sens, ponieważ 6.2.5p6 wymaga int i unsigned int do wykorzystania tej samej ilości pamięci. Mimo, że printf% d na unsigned jest technicznie nieokreślony, nie ma żadnego wiarygodnego powodu, aby powodował prawdziwe problemy. – Chris

+0

Standard nie mówi, że 'printf()' używa '', ale fakt, że możesz utworzyć wskaźnik do funkcji 'printf()' może wywoływać przez nią implikuje przynajmniej pewne cechy wspólne w mechanizmie przekazywania argumentów . –

+3

GCC 5.0 ma teraz takie ostrzeżenie: ['-Wformat-signedness'] (https://gc.gnu.org/bugzilla/show_bug.cgi?id=60194) (włączone przez' -Wformat'). – cremno

Powiązane problemy