2012-03-30 20 views
15

fragment kodu:Ostrzeżenie: ta stała dziesiętna jest niepodpisany tylko w ISO C90

long rangeVar = 0; 
rangeVar = atol(p_value); 

if (rangeVar >= -2147483648 && rangeVar <= 2147483647) 

Na kompilacji otrzymuję:

ostrzeżenie: ta stała dziesiętna jest niepodpisany tylko w ISO C90

Z góry dzięki

+1

C90 nie ma typu 'long long', dlatego obsługuje takie numery inaczej niż C99. – Lindydancer

+2

FYI: Poprawną odpowiedź można znaleźć tutaj: http://stackoverflow.com/questions/2347936/cant-get-rid-of-this-decimal-constant-is-unsigned-only-in-iso-c90- ostrzeżenie – natersoz

Odpowiedz

9

Tak, jedna rzecz nie jest dobrze obsługiwana przez kompilator. Problem polega na tym, że podczas kompilacji jest to liczba 2147483648, która jest zanegowana, a 2147483648 jest poza zakresem dla liczby całkowitej. Nawet jeśli -2147483648 nie byłoby!

W każdym razie, aby pozbyć się ostrzeżenia, można zmienić stałą na 64-bitową liczbę, pisząc -2147483648LL.
To jednak przesada, więc preferowaną metodą byłoby użycie stałej o wartości INT_MIN. Ale wtedy musisz dołączyć <limits.h>.

+2

Nie całkowicie poprawne/dokładne. C89 mówi: 'Typ stałej liczbowej jest pierwszą z odpowiedniej listy, na której można przedstawić jej wartość. Unsuffixed decimal: int, long int, unsigned long int; niedostosowane ósemkowe lub szesnastkowe: ... '. Tak więc, dla starego kompilatora lub nowoczesnego kompilatora działającego w jakimś trybie zgodności 2147483648 zawiedzie, jeśli nie pasuje do 'unsigned long', a nie plain' int'. C99 rozszerza tę listę o 'long long int' i' unsigned long long int' oraz w trybie C99 przyrostek (U) LL jest niepotrzebny. Oczywiście błędy kompilatora również nie są niespotykane. –

+0

Jak wytłumaczysz wtedy ostrzeżenie? Przetestowałem i otrzymałem takie samo ostrzeżenie, co OP z gcc 4.3.2, i bez ostrzeżenia, gdy użyłem sufiksu LL. –

+0

Oznacza to, że gcc nie jest domyślnie w trybie C99. Jeśli dodasz '-std = c99', pojawi się inne ostrzeżenie:" porównanie jest zawsze prawdziwe z powodu ograniczonego zakresu typu danych ". Niespodzianka. Nie jestem nawet pewien, który tryb jest domyślnie i dlaczego. –

1

Tak, 2147483648 nie jest poprawną wartością dodatnią, ponieważ jest poza zakresem dla uzupełnienia do 2 na 32-bitowych maszynach, więc próbują ostrzec cię, że w niektórych kompilatorach może nie dać ci pożądanej wartości, jeśli nie zajmuj się negacją w nowoczesny sposób.

Uważam, że warto dodać kolejną odpowiedź, aby wskazać, że jeśli spojrzysz na większość implementacji limits.h, zobaczysz, że obchodzą się z tym przy użyciu (-2147483647 - 1).

+0

świetna sztuczka !! – malat

12

Reguły dla typów dziesiętnych stałych całkowitych uległy zmianie w latach 1990-1999 w standardzie ISO C.

W wersji 1990 danego typu unsuffixed dziesiętna stałą całkowitą jest pierwszy int, long int lub unsigned long int w którym jego wartość może być reprezentowanych. (C90 nie miał typu long long lub unsigned long long).

W wersjach 1999 i 2011 jego typ jest jednym z int, long int, long long int; nigdy nie jest typu bez znaku.

Typ konkretnej stałej (np. 2147483648) będzie różny w zależności od zakresów typów całkowitych używanego kompilatora. Jeśli typ kompilatora to long jest 32-bitowy, wówczas 2147483648 będzie typu unsigned long, jeśli twój kompilator używa reguł C90, lub typu long long, jeśli używa reguł C11 (gwarantowane jest co najmniej 64 bity) (long long). Kompilator ostrzega cię o tym.

Możesz dodać przyrostki, aby określić typ stałej - ale nie ma sufiksu dla zwykłego podpisu int. Możesz dodać U dla unsigned int, L dla long, UL dla niepodpisanych długich i tak dalej.

Należy pamiętać, że -2147483648 to nie stała całkowita; raczej 2147483648 sama w sobie jest stałą całkowitą, a -2147483648 jest wyrażeniem, które stosuje jednoargumentowy operator minus do tej stałej.Zgodnie z regułami C90, jeśli stała jest typu unsigned long, jest to niepodpisany jednoargumentowy minus, który zgodnie z regułami niepodpisanej arytmetycznej daje wartość 2147483648. Zgodnie z regułami C99 lub C11, 2147483648 jest prawdopodobnie typu (podpis) long long, a negowanie go daje -2147483648, również typu long long.

Czasami zobaczysz kod, który używa (-2147483647 - 1), aby uniknąć tego problemu; biorąc pod uwagę 32-bitowe int, 2147483647 jest typu int, a wynik wyrażenia daje oczekiwaną wartość int bez przepełnienia.

Oczywiście, jeśli twój kompilator ma różne rozmiary dla typów całkowitych, może to być jeszcze bardziej skomplikowane.

+0

Dziękuję za wspaniałą i jasną odpowiedź. Dla kompletności warto dodać, że wydanie 1999 o standardzie C wspomniano o _extended integer types definiowanych przez implementację_. Jeśli żaden z typów nie jest wystarczający, to stała może mieć taki rozszerzony typ, jak ostatni. Na przykład w GCC (wersja 4.4.7) stała "9223372036854775808" (tj. 2^63) jest "promowana" do 16 bajtów typu "__int128_t" (pomimo faktu, że nie jest "prawdziwym" EIT). Należy również zauważyć, że te zasady są nieco inne w przypadku ósemkowych i szesnastkowych reprezentacji, ale myślę, że OP był zainteresowany tylko dziesiętnymi. –

+1

Sufiks "U" oznacza niepodpisany, ale niekoniecznie "unsigned int", np. jeśli stała dziesiętna z 'U' jest zbyt duża dla' unsigned int', będzie miała typ 'unsigned long'. Podobnie, 'L' będzie" aktualizować "do' long long', jeśli wartość nie pasuje do 'long'. –