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
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)). –
Ź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). –