jaki jest powód jawnego deklarowania wartości L lub UL dla długich

Z przykładu

unsigned long x = 12345678UL

Zawsze dowiedzieliśmy się, że kompilator musi widzieć tylko "long" w powyższym przykładzie, aby ustawić 4 bajty (w 32 bitach) pamięci. Pytanie brzmi, Dlaczego powinniśmy używać L / UL w stałych długich, nawet po zadeklarowaniu, że jest długa.

 23
Author: Shash, 2012-10-30

4 answers

Gdy nie jest używany sufiks L lub UL, kompilator używa pierwszego typu, który może zawierać stałą z listy(patrz szczegóły w standardzie C99, klauzula 6.4.4: 5. Dla stałej dziesiętnej lista jest int, long int, long long int).

W konsekwencji, w większości przypadków, nie jest konieczne używanie przyrostka. Nie zmienia to znaczenia programu. Nie zmienia to znaczenia przykładowej inicjalizacji x dla większości architektur, chociaż byłoby, gdybyś wybrał Liczba, której nie można przedstawić jako long long. Zobacz także odpowiedź codebauera dla przykładu, w którym potrzebna jest część U sufiksu.


Istnieje kilka okoliczności, w których programista może chcieć ustawić typ stałej jawnie. Przykładem może być funkcja zmienna:

printf("%lld", 1LL); // correct
printf("%lld", 1);   // undefined behavior

Częstym powodem użycia sufiksu jest zapewnienie, że wynik obliczeń nie przepełni się. Dwa przykłady to:

long x = 10000L * 4096L;
unsigned long long y = 1ULL << 36;

W obu przykładach, bez przyrostków, stałe będą miały typ int, a obliczenia będą wykonane jako int. W każdym przykładzie wiąże się to z ryzykiem przepełnienia. Użycie przyrostków oznacza, że obliczenia będą wykonywane w większym typie, który ma wystarczający zakres dla wyniku.

Jak to ujął Lightness Races in Orbit, sufiks litterala pojawia się przed przypisaniem. W dwóch powyższych przykładach samo zadeklarowanie x jako long i y jako unsigned long long nie wystarczy, aby zapobiec przepełnienie w obliczeniach przypisanych do nich wyrażeń.


Innym przykładem jest porównanie x < 12U gdzie zmienna x mA typ int. Bez sufiksu U kompilator typuje stałą {[22] } jako int, a więc porównanie jest porównaniem podpisanych int.

int x = -3;
printf("%d\n", x < 12); // prints 1 because it's true that -3 < 12

Z przyrostkiem U, porównanie staje się porównaniem niepodpisanych int. "Zwykłe konwersje arytmetyczne" oznaczają, że -3 jest konwertowane na duży niepodpisany int:

printf("%d\n", x < 12U); // prints 0 because (unsigned int)-3 is large
W rzeczywistości Typ stałej może nawet zmienić wynik obliczeń arytmetycznych, ponownie ze względu na sposób działania "zwykłych konwersji arytmetycznych".

Zauważ, że dla stałych dziesiętnych lista typów sugerowanych przez C99 nie zawiera unsigned long long. W C90 lista kończyła się największym standaryzowanym typem unsigned integer w tamtym czasie (którym był unsigned long). Konsekwencją było to, że znaczenie niektórych programów zostało zmienione przez dodanie standardowego typu long long do C99: ta sama stała, która została wpisana jako unsigned long W C90, może być teraz wpisana jako Podpisane long long. Uważam, że to jest powód, dla którego w C99, zdecydowano nie mieć unsigned long long na liście typów dla stałych dziesiętnych. Zobacz ten i ten blog posty dla przykładu.

 50
Author: Pascal Cuoq,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 13:54:18

Ponieważ literały liczbowe są typowo typu int. UL / L mówi kompilatorowi, że nie są one typu int, np. zakładając 32-bitowy int i 64-bitowy long

long i = 0xffff;
long j = 0xffffUL;

Tutaj wartości po prawej stronie MUSZĄ BYĆ przekonwertowane na podpisane Longi (32bit -> 64bit)

  1. "0xFFFF", int, zostanie przekonwertowany na long za pomocą rozszerzenia znaku, co da wartość ujemną (0xffffffff)
  2. "0xfffful", niepodpisana długa, zostanie przekonwertowana na długą, co da wartość dodatnią (0x0000ffff)
 8
Author: codebauer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 08:40:25

Pytanie brzmi, Dlaczego powinniśmy używać L / UL w stałych długich, nawet po zadeklarowaniu, że jest długa.

Ponieważ nie jest "po", tylko "przed".

Najpierw masz literał, Następnie jest on konwertowany do dowolnego typu zmiennej, w którą próbujesz ją wcisnąć.

 5
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-30 12:47:44

Związane z tym postem jest dlaczego u.

Powodem u jest dopuszczeniestałej całkowitej większej niż LLONG_MAX w postaci dziesiętnej.

// Likely to generate a warning.
unsigned long long limit63bit = 18446744073709551615`; // 2^64 - 1

// OK
unsigned long long limit63bit = 18446744073709551615u`;
 0
Author: chux,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-26 15:17:00