2016-07-17 15 views
6

Natknąłem się na to pytanie.Dlaczego wynik tego kodu C to "nie"?

#include <stdio.h> 

int main(void) { 
    // your code goes here 
    unsigned int i = 23; 
    signed char c = -23; 

    if (i > c) 
     printf("yes"); 
    else 
     printf("no"); 

    return 0; 
} 

Jestem w stanie zrozumieć, dlaczego jest wyjście z tego kodu jest no.

Czy ktoś może mi pomóc zrozumieć, w jaki sposób działa operator porównania, gdy porównuje się między int i char w C?

+4

przeczytać o [uzupełnienie dwójkowe] (https://en.wikipedia.org/wiki/Two%27s_complement). oraz o [niejawne konwersje w C] (http: //en.cppreference.com/w/c/language/conversion) (szczególnie o [konwersjach arytmetycznych] (http://en.cppreference.com/w/c/language/conversion#Usual_arithmetic_conversions)). –

+0

Źródłem kanonicznym jest [standard C] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) (to jest szkic N1570). Zobacz 6.3.1.1 dla * promocji liczb całkowitych * (które konwertują wartość 'signed char' na' int') i 6.3.1.8 dla * zwykłych konwersji arytmetycznych * (które przekształcają oba operandy na typ wspólny, 'unsigned int' , przed wykonaniem porównania). –

Odpowiedz

11

Porównujesz unsigned int do . Semantyka tego rodzaju porównania jest sprzeczna z intuicją: większość operacji binarnych z operandami signed i unsigned jest wykonywana na niepodpisanych operandach, po konwersji wartości podpisanej na niepodpisaną (jeśli oba operandy mają ten sam rozmiar po promocji). Oto kroki:

  • Wartość signed char jest promowany do int o tej samej wartości -23.
  • porównanie należy przeprowadzić na int i unsigned int, typem wspólnym jest unsigned int zgodnie z definicją w standardzie C.
  • Urządzenie int jest konwertowane na unsigned int o wartości UINT_MAX - 23, bardzo dużej liczbie.
  • Porównanie jest wykonywane na wartościach unsigned int: 23 jest mniejszą wartością, porównanie jest wynikiem fałszywym.
  • Oddział else jest oceniany, drukowany jest no.

Co gorsza, jeśli c została zdefiniowana jako long, wynik byłby zależała od tego, czy long i int mają tę samą wielkość, czy nie. W systemie Windows wydrukowałby on no, podczas gdy w 64-bitowym systemie Linux wydrukowałby on yes.

Nigdy nie mieszaj podpisanych i niepodpisanych wartości w porównaniach. Włącz ostrzeżenia kompilatora, aby zapobiec tego rodzaju błędom (-Wall lub -Weverything). Równie dobrze możesz zgodzić się na te ostrzeżenia z -Werror, aby całkowicie uniknąć tego rodzaju niefortunnego kodu.

Pełną odniesienia można znaleźć w następujących odcinków C Standard (C11) w 6,3 konwersji:

  • promocji całkowite objaśnione w 6.3.1.1 logicznych, postacie i całkowite .
  • Konwersje operandów są szczegółowo opisane w 6.3.1.8 Zwykłe konwersje arytmetyczne.

można pobrać najnowszy projekt standardu C11 ze strony grupy roboczej: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

+0

Przydatne referencje jako uzupełnienie tej odpowiedzi: https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules – chrphb

+0

i 6.3.1.1 dla promocji * z liczbą całkowitą *. [Oto link] (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) do wersji N1570 standardu C11. –

Powiązane problemy