2012-05-17 18 views
5

Chcę móc używać dużych dodatnich liczb całkowitych (8 bajtów) w moim projekcie, mimo że sizeof (unsigned long) daje 8 w moim systemie, czytałem, że w większość systemów bez znaku ma tylko 4 bajty i zdecydowałem się dać niepodpisany długi czas, ponieważ gwarantowane jest co najmniej 8 bajtów.unsigned long long vs unsigned long (przenośność punktu widzenia)

Im więcej go używam, jednak widzę, że nie jest on również super przenośny, na przykład w niektórych systemach (w zależności od kompilatora) printf formatuje go za pomocą% llu, w niektórych formatuje go za pomocą% lld.

Mój kod będzie działać tylko na 64-bitowych urządzeniach debian, w których bez znaku długi będzie wynosił 8 bajtów. Przenośność nie jest dużym problemem. Czy w takich okolicznościach przesada jest zbyt długa, niepoprawnie długa, czy istnieją inne zalety używania niepodpisanych długich i niepoprawnie długich?

+7

Czy próbowałeś 'uint64_t'? To jest w ' .' – Mysticial

+0

jaka jest zaleta używania go przez dłuższy czas bez znaku? –

+1

Zatrzymuje kompilację, jeśli nie masz typu z dokładnie 64 bitami, a długiego wzdłuż dłuższego typu. Oba są obecne w C++ 11, oba są często obecne jako rozszerzenie, ale nie byłbym zaskoczony, gdyby jeden był czasem obecny, a nie inny.Jeśli go nie masz, stdint.h jest łatwiej emulować (zakładając, że typ jest obecny) niż długo. – AProgrammer

Odpowiedz

9

unsigned long long ma co najmniej 64 bity, niezależnie od platformy. (Są platformy, na których jest więcej — Wiem o 72 bitach i 96 bitach —, ale są one rzadkie i zdecydowanie egzotyczne.) unsigned long ma co najmniej 32 bity. Jeśli potrzebujesz więcej niż 32-bitów, polecam unsigned long long.

Jeśli chodzi o formatowanie, z printf należy użyć "%llu" (ponieważ jest bez znaku); "%lld" jest dla signed long long.

+0

dzięki James, to też myślałem, że zdecydowanie bezpieczniej jest używać unsigned long long. Oto jednak pytanie: Ponieważ w moim środowisku programistycznym i docelowym unsigned long jest 8 bajtów, czy mogę po prostu odejść używając zamiast unsigned long? Przy okazji kompilator generuje ostrzeżenie, gdy używam% llu z niepodpisaną długością, tego rodzaju niestabilności odstraszają mnie od używania niepodpisanego długiego czasu. –

+0

Czy gwarancja "co najmniej 64-bitowa" nie jest dostępna od czasu C++ 11? – juanchopanza

+0

@erinc Jeśli pracujesz na platformie, w której zarówno 'long long' i' long' mają ten sam rozmiar, wygenerowany kod powinien być identyczny dla nich, więc nie ma powodu, aby nie używać 'long long'. A jeśli kompilator ostrzega podczas przekazywania 'unsigned long long' do' "% llu" ', może to być uznane za błąd. Jedynym legalnym typem przekazywanym do '"% llu "' jest 'unsigned long long'; przekazanie jakiegokolwiek innego typu jest niezdefiniowanym zachowaniem. –

0

Jeśli musisz upewnić się, że masz stały rozmiar wartości całkowitej, niezależnie od platformy, możesz użyć biblioteki boost :: integers (patrz here). Możesz użyć boost :: int64_t lub boost :: uint64_t dla wartości unsigned

+0

dlaczego warto używać boost, a nie stdint.h uint64_t? – WeaselFox

0

Można to zrobić, jeśli chcesz pozostać z długo i długo długo:

#include <limits.h> 
#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL 
typedef unsigned long uint64; 
#else 
typedef unsigned long long uint64; 
#endif 

W.r.t. to

w niektórych systemach (w zależności od kompilatora) formatów go printf z% LLU, w niektórych formatach to go% LLD

printf() nie odgadnąć formatu. Mówisz mu format.

Jeśli chcesz printf do uint64 zdefiniowane jak w powyższym zrobić to tak:

printf("%llu", (unsigned long long)some_uint64_value);

Można typedef unsigned long long ulonglong; aby odlew łatwiej pisać.

Istnieją inne sposoby robienia tego samego, ale nie wszystkie kompilatory je obsługują. To dlatego dołączyłem przyrostek ULL do numeru. W niektórych trybach zgodności pomiędzy C89 i C99, 0xFFFFFFFFFFFFFF może być interpretowane jako unsigned long, a nie unsigned long long i będzie obcięte. Najnowszy domyślny gcc działa w trybie gnu89 dla kodu C, a nie c99 lub nowszego.