Czy można bezpiecznie używać -1, aby ustawić wszystkie bity na true?
Widziałem ten wzór używany wiele W C & C++.
unsigned int flags = -1; // all bits are true
Czy to dobry przenośny sposób, aby to osiągnąć? Czy używanie 0xffffffff
lub ~0
jest lepsze? 19 answers
Polecam Ci zrobić to dokładnie tak, jak pokazałeś, ponieważ jest to najbardziej prosta droga. Inicjalizuj do -1
, które będzie działać zawsze , niezależnie od rzeczywistej reprezentacji znaku, podczas gdy ~
będzie czasami miało zaskakujące zachowanie, ponieważ będziesz musiał mieć odpowiedni typ operandu. Dopiero wtedy otrzymasz najwyższą wartość typu unsigned
.
Dla przykładu możliwej niespodzianki, rozważ ten:
unsigned long a = ~0u;
Niekoniecznie będzie przechowywać wzorzec ze wszystkimi bitami 1 na a
. Ale najpierw utworzy wzorzec ze wszystkimi bitami 1 w unsigned int
, a następnie przypisze go do a
. Co się dzieje, gdy unsigned long
ma więcej bitów, to nie wszystkie z nich są 1.
I rozważ tę, która zawiedzie na reprezentacji dopełniacza nie-dwójki:
unsigned int a = ~0; // Should have done ~0u !
Powodem tego jest to, że ~0
musi odwrócić wszystkie bity. Odwrócenie, które da -1
na maszynie dopełniacza dwójki (która jest wartością, której potrzebujemy!), ale Nie da -1
na innej reprezentacji. Na maszynie dopełniającej jedynki daje zero. Tak więc, na maszynie dopełniacza, powyższe inicjalizuje a
do zera.
Rzeczą, którą powinieneś zrozumieć jest to, że chodzi o wartości - nie o bity. Zmienna jest inicjalizowana wartością . Jeśli w inicjalizatorze zmodyfikujesz bity zmiennej używanej do inicjalizacji, wartość zostanie wygenerowana zgodnie z tymi bitami. Wartość, której potrzebujesz, aby zainicjować a
do najwyższego możliwa wartość to -1
lub UINT_MAX
. Drugi będzie zależał od typu a
- będziesz musiał użyć ULONG_MAX
dla unsigned long
. Jednak pierwszy nie zależy od jego rodzaju i jest to miły sposób na uzyskanie najwyższej wartości.
Nie mówimy o tym, czy -1
ma wszystkie bity jeden (nie zawsze ma). A my Nie mówimy o tym, czy ~0
ma wszystkie bity jeden (oczywiście ma).
Ale mówimy o tym, co wynikiem zainicjalizowanej zmiennej flags
jest. I za to, tylko -1
będzie działać z każdym typem i maszyną.
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
2013-03-12 23:28:40
-
unsigned int flags = -1;
jest przenośny. -
unsigned int flags = ~0;
nie jest przenośny, ponieważ polega na reprezentacji dwójki-dopełniacza. -
unsigned int flags = 0xffffffff;
nie jest przenośny, ponieważ zakłada 32-bitowe ints.
Jeśli chcesz ustawić wszystkie bity w sposób gwarantowany przez standard C, użyj pierwszego.
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
2011-11-21 09:03:25
Szczerze mówiąc myślę, że wszystkie fff są bardziej czytelne. Jeśli chodzi o komentarz, że jego antypattern, jeśli naprawdę zależy ci na tym, że wszystkie bity są ustawione/wyczyszczone, argumentowałbym, że prawdopodobnie jesteś w sytuacji, w której zależy ci na wielkości zmiennej i tak, co wymagałoby czegoś takiego jak boost:: uint16_t, itp.
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
2009-04-30 21:42:34
Sposobem na uniknięcie wspomnianych problemów jest po prostu zrobić:
unsigned int flags = 0;
flags = ~flags;
Przenośny i do rzeczy.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
2009-05-01 13:26:28
Nie jestem pewien, czy używanie niepodpisanej liczby całkowitej dla FLAG jest dobrym pomysłem w C++. A co z bitsetem i tym podobnymi?
std::numeric_limit<unsigned int>::max()
jest lepsze, ponieważ 0xffffffff
zakłada, że niepodpisana liczba całkowita jest 32-bitową liczbą całkowitą.
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-12-10 05:26:20
Przenośny? Tak . Dobrze? dyskusyjne , o czym świadczy całe zamieszanie pokazane w tym wątku. Bycie wystarczająco jasnym, aby Twoi koledzy programiści mogli zrozumieć kod bez nieporozumień, powinno być jednym z wymiarów, które mierzymy dla dobrego kodu.unsigned int flags = -1; // all bits are true
" czy jest to dobry [,] przenośny sposób, aby to osiągnąć?"
Ponadto, ta metoda jest podatna na ostrzeżenia kompilatora. Aby uniknąć ostrzeżenia bez uszkadzania kompilatora, potrzebujesz wyraźnej obsady. Na przykład,
unsigned int flags = static_cast<unsigned int>(-1);
Wyraźna Obsada wymaga zwrócenia uwagi na typ celu. Jeśli zwracasz uwagę na typ celu, naturalnie unikniesz pułapek innych podejść.
Radzę zwrócić uwagę na typ celu i upewnić się, że nie ma ukrytych konwersji. Na przykład:
unsigned int flags1 = UINT_MAX;
unsigned int flags2 = ~static_cast<unsigned int>(0);
unsigned long flags3 = ULONG_MAX;
unsigned long flags4 = ~static_cast<unsigned long>(0);
Wszystkie z nich są poprawne i bardziej oczywiste dla kolegów programistów.
Oraz w C++11: możemy użyć auto
, aby uczynić dowolne z nich jeszcze prostszym:
auto flags1 = UINT_MAX;
auto flags2 = ~static_cast<unsigned int>(0);
auto flags3 = ULONG_MAX;
auto flags4 = ~static_cast<unsigned long>(0);
Uważam poprawność i oczywistość za lepsze niż po prostu poprawność.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
2013-05-02 12:35:52
Konwersja -1 na dowolny niepodpisany typ jest gwarantowana przez standard , aby skutkować all-ones. Użycie ~0U
jest ogólnie złe, ponieważ 0
mA typ unsigned int
i nie wypełni wszystkich bitów większego, niepodpisanego typu, chyba że wyraźnie napiszesz coś w rodzaju ~0ULL
. W systemach sane ~0
powinny być identyczne z -1
, ale ponieważ standard dopuszcza reprezentacje-dopełniacza i znaku / wielkości, ściśle mówiąc nie jest przenośny.
Oczywiście zawsze można pisać out 0xffffffff
jeśli wiesz, że potrzebujesz dokładnie 32 bitów, ale -1 ma tę zaletę, że będzie działać w każdym kontekście, nawet jeśli nie znasz rozmiaru typu, np. makr, które działają na wielu typach, lub jeśli Rozmiar typu różni się w zależności od implementacji. Jeśli znasz typ, innym bezpiecznym sposobem na uzyskanie wszystkich jest makra limit UINT_MAX
, ULONG_MAX
, ULLONG_MAX
, itd.
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
2010-08-01 21:02:49
Tak. Jak wspomniano w innych odpowiedziach, -1
jest najbardziej przenośny; jednak nie jest zbyt semantyczny i wyzwala ostrzeżenia kompilatora.
Aby rozwiązać te problemy, spróbuj tego prostego pomocnika:
static const struct All1s
{
template<typename UnsignedType>
inline operator UnsignedType(void) const
{
return static_cast<UnsignedType>(-1);
}
} ALL_BITS_TRUE;
Użycie:
unsigned a = ALL_BITS_TRUE;
uint8_t b = ALL_BITS_TRUE;
uint16_t c = ALL_BITS_TRUE;
uint32_t d = ALL_BITS_TRUE;
uint64_t e = ALL_BITS_TRUE;
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
2013-07-16 05:32:57
Tak długo, jak masz #include <limits.h>
jako jeden ze swoich includes, należy po prostu użyć
unsigned int flags = UINT_MAX;
Jeśli chcesz mieć długą wartość bitów, możesz użyć
unsigned long flags = ULONG_MAX;
Te wartości gwarantują, że wszystkie bity wartości wyniku będą ustawione na 1, niezależnie od tego, w jaki sposób zaimplementowane są liczby całkowite podpisane.
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-01-04 00:23:31
Nie zrobiłbym tego. Jest raczej nieintuicyjny (przynajmniej dla mnie). Przypisywanie podpisanych danych do niepodpisanej zmiennej wydaje się naruszać naturalny porządek rzeczy.
W twojej sytuacji zawsze używam 0xFFFF
. (Użyj odpowiedniej liczby Fs dla zmiennej wielkości oczywiście.)
[BTW, bardzo rzadko widzę trick -1 wykonywany w kodzie realnym.]
Dodatkowo, jeśli naprawdę zależy ci na poszczególnych bitach w vairable, dobrze byłoby zacząć używać Stała szerokość uint8_t
, uint16_t
, uint32_t
typy.
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-12-10 05:24:21
Na procesorach Intela IA-32 można zapisać 0xFFFFFFFF do rejestru 64-bitowego i uzyskać oczekiwane wyniki. Dzieje się tak dlatego ,że IA32e (64-bitowe rozszerzenie do IA32) obsługuje tylko 32-bitowe W instrukcjach 64-bitowych 32-bitowe są znak-rozszerzone do 64-bitów.
Poniższe jest nielegalne:
mov rax, 0ffffffffffffffffh
Następujące umieszcza 64 1s w RAX:
mov rax, 0ffffffffh
Tylko dla kompletności, następujące umieszcza 32 1s w dolnej części RAX (aka EAX):
mov eax, 0ffffffffh
Oraz w rzeczywistości miałem niepowodzenie programów, gdy chciałem napisać 0xffffffffffff do zmiennej 64-bitowej i zamiast tego dostałem 0xffffffffffffffffffffff. W C będzie to:
uint64_t x;
x = UINT64_C(0xffffffff)
printf("x is %"PRIx64"\n", x);
Wynik jest następujący:
x is 0xffffffffffffffff
Pomyślałem, że wrzucę to jako komentarz do wszystkich odpowiedzi, które mówiły, że 0xFFFFFFFF zakłada 32 bity, ale tak wiele osób na to odpowiedziało, że pomyślałem, że dodam to jako oddzielną odpowiedź.
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
2009-05-02 10:53:37
Zobacz odpowiedź litb, aby uzyskać bardzo jasne wyjaśnienie problemów.
Moja niezgoda jest taka, że, bardzo ściśle mówiąc, nie ma żadnych gwarancji dla obu przypadków. Nie znam żadnej architektury, która nie reprezentuje niepodpisanej wartości "jeden mniej niż dwa do potęgi liczby bitów", jak wszystkie bity ustawione, ale oto, co Standard faktycznie mówi (3.9.1 / 7 plus Uwaga 44):
Reprezentacje typów całkowych definiują wartości za pomocą czystej binarnej system numeracji. [Uwaga 44:] reprezentacja pozycyjna dla liczb całkowitych, która używa cyfr binarnych 0 i 1, w której wartości reprezentowane przez kolejne bity są addytywne, rozpoczynają się od 1 i są mnożone przez kolejne potęgi całkowe 2, z wyjątkiem być może dla bitu o najwyższej pozycji.
To pozostawia możliwość, że jeden z bitów będzie cokolwiek.
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
2009-05-12 13:41:33
Praktycznie: Tak
Teoretycznie: Nie.
-1 = 0xFFFFFFFF (lub jakikolwiek Rozmiar int jest na twojej platformie) jest prawdziwy tylko z arytmetyką dopełniacza two. W praktyce będzie działać, ale istnieją starsze maszyny tam (IBM mainframe, itp.) gdzie masz znak rzeczywisty, a nie reprezentację dopełniacza dwójki. Proponowane rozwiązanie ~0 powinno działać wszędzie.
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
2009-04-30 21:41:52
Chociaż 0xFFFF
(LUB 0xFFFFFFFF
, itp.) może być łatwiejszy do odczytania, może złamać przenośność w kodzie, który w przeciwnym razie byłby przenośny. Rozważ na przykład procedurę biblioteczną, aby policzyć, ile elementów w strukturze danych ma ustawione określone bity(dokładne bity określone przez wywołującego). Procedura może być całkowicie agnostyczna co do tego, co reprezentują bity, ale nadal musi mieć stałą "wszystkie bity ustawione". W takim przypadku -1 będzie znacznie lepsze niż stała szesnastkowa, ponieważ będzie działać z dowolny rozmiar bitów.
Inną możliwością, jeśli dla maski bitowej używana jest wartość typedef
, byłoby użycie ~(bitmaskttype)0; jeśli maska bitowa jest tylko 16-bitowym typem, to wyrażenie będzie miało ustawione tylko 16 bitów (nawet jeśli 'int' byłby 32 bitami), ale ponieważ 16 bitów będzie wszystkim, co jest wymagane, wszystko powinno być dobrze pod warunkiem, że ktoś faktycznie używa odpowiedniego typu w typecast.
Nawiasem mówiąc, wyrażenia postaci longvar &= ~[hex_constant]
mają paskudną, jeśli hex stała jest zbyt duża, aby zmieścić się w int
, ale zmieści się w unsigned int
. Jeśli int
jest 16 bitami, to longvar &= ~0x4000;
lub longvar &= ~0x10000
; wyczyści jeden bit longvar
, ale longvar &= ~0x8000;
wyczyści bit 15 i wszystkie bity powyżej tego. Wartości pasujące do int
będą miały operator dopełniacza zastosowany do typu int
, ale wynik będzie znak rozszerzony do long
, ustawiając górne bity. Wartości, które są zbyt duże dla unsigned int
, będą miały operator dopełniacza zastosowany do typu long
. Wartości pomiędzy tymi rozmiarami, zastosuje jednak operator dopełniacza do typu unsigned int
, który następnie zostanie przekonwertowany na typ long
bez rozszerzenia znaku.
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-12-10 16:09:34
Jak wspomnieli inni, -1 jest poprawnym sposobem tworzenia liczby całkowitej, która przekształci się w typ niepodpisany ze wszystkimi bitami ustawionymi na 1. Jednak najważniejszą rzeczą w C++ jest używanie poprawnych typów. Dlatego prawidłowa odpowiedź na twój problem (która zawiera odpowiedź na zadane pytanie) jest następująca:
std::bitset<32> const flags(-1);
To zawsze będzie zawierać dokładną ilość bitów, których potrzebujesz. Konstruuje std::bitset
ze wszystkimi bitami ustawionymi na 1 z tych samych powodów wymienionych w innych odpowiedziach.
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-12-12 02:26:58
Jest to na pewno bezpieczne, ponieważ -1 zawsze będzie miało ustawione wszystkie dostępne bity, ale wolę ~0. -1 po prostu nie ma sensu dla unsigned int
. 0xFF
... nie jest dobre, ponieważ zależy od szerokości typu.
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
2009-04-30 21:40:28
Mówię:
int x;
memset(&x, 0xFF, sizeof(int));
To zawsze daje pożądany rezultat.
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
2010-10-11 11:28:57
Wykorzystując fakt, że przypisanie wszystkich bitów do jednego dla typu niepodpisanego jest równoważne z pobieraniem maksymalnej możliwej wartości dla danego typu,
i rozszerzenie zakresu pytania na wszystkie unsigned typy całkowite:
Przypisanie -1 działa dla dowolnego typu unsigned integer (unsigned int, uint8_t, uint16_t, itd.) zarówno dla C jak i C++.
Jako alternatywę dla C++ możesz:
- Include
<limits>
and usestd::numeric_limits< your_type >::max()
W związku z tym, że typ docelowy jest typem unsigned, nie jest to typ docelowy, który może być przypisany do danego typu docelowego.]}
Celem może być dodanie większej jasności, ponieważ przypisanie -1
zawsze wymagałoby jakiegoś komentarza wyjaśniającego.
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
2017-05-23 10:31:10
Tak pokazana reprezentacja jest bardzo poprawna, jak gdybyśmy zrobili to w drugą stronę, U będzie wymagało od operatora odwrócenia wszystkich bitów, ale w tym przypadku logika jest dość prosta, jeśli weźmiemy pod uwagę rozmiar liczb całkowitych w maszynie
Na przykład w większości maszyn liczba całkowita wynosi 2 bajty = 16 bitów. 2^16-1=65535 2^16=65536
0%65536=0 -1%65536=65535 co odpowiada 1111.............1 i wszystkie bity są ustawione na 1 (jeśli weźmiemy pod uwagę klasy pozostałości mod 65536) stąd jest to bardzo proste.
Chyba
No jeśli uznasz to pojęcie to jest idealnie dla niepodpisanych ints i faktycznie działa
Wystarczy sprawdzić następujący fragment programu
Int main() {
unsigned int a=2;
cout<<(unsigned int)pow(double(a),double(sizeof(a)*8));
unsigned int b=-1;
cout<<"\n"<<b;
getchar();
return 0;
}
Odpowiedź dla b = 4294967295 whcih wynosi -1% 2^32 na 4-bajtowych liczbach całkowitych
Stąd jest doskonale poprawny dla niepodpisanych liczb całkowitych
W przypadku jakichkolwiek rozbieżności raport plzz
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
2010-10-11 09:32:44