Mam dziwny problem z pracą z liczbami całkowitymi w C ++.
Napisałem prosty program, który ustawia wartość zmiennej, a następnie ją drukuje, ale nie działa zgodnie z oczekiwaniami.
Mój program ma tylko dwie linie kodu:
uint8_t aa = 5;
cout << "value is " << aa << endl;
Wynik tego programu to value is
To znaczy, drukuje puste dla aa
.
Kiedy zmieni uint8_t
się uint16_t
powyższy kod działa jak czar.
Używam Ubuntu 12.04 (Precise Pangolin), 64-bitowego, a moja wersja kompilatora to:
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
Odpowiedzi:
Tak naprawdę nie wypisuje spacji, ale najprawdopodobniej znak ASCII o wartości 5, który jest niedrukowalny (lub niewidoczny). Istnieje wiele niewidocznych kodów znaków ASCII , większość z nich poniżej wartości 32, która w rzeczywistości jest pusta.
Musisz przekonwertować
aa
na,unsigned int
aby wyświetlić wartość liczbową, ponieważostream& operator<<(ostream&, unsigned char)
próbuje wyświetlić widoczną wartość znaku.źródło
int
. Obsada to jeden ze sposobów, ale nie jedyny.+aa
również działa.int(var)
i(int)var
miał dokładnie to samo znaczenie.int(var)
jest odradzany dokładnie w tych przypadkach, w których(int)var
jest, z dokładnie tych samych powodów, ponieważ oznacza dokładnie to samo. (Rozumiem jednak, dlaczego i tak zdecydowałeś się na to tutaj, więc nie mówię, że musisz go używaćstatic_cast
. Myślę tylko, że ścieżka komentarzy tutaj jest trochę niepotrzebnie myląca.)uint8_t
najprawdopodobniej będzietypedef
forunsigned char
.ostream
Klasa ma szczególne przeciążenia dlaunsigned char
, tj drukuje znak z numerem 5, która jest nie do druku, stąd pustej przestrzeni.źródło
Dodanie jednoargumentowego operatora + przed zmienną dowolnego pierwotnego typu danych da drukowalną wartość liczbową zamiast znaku ASCII (w przypadku typu char).
źródło
uint8_t
jakounsigned char
wartości liczbowych?uint8_t
jest tylko typem defunsigned char
,unsigned char
sam jest obsługiwany przezostream
to samochar
i wyświetla swoją wartość ASCII.unsigned char
który wiele wyjaśnia. Więc jedyną liczbą całkowitą jestint
, prawda?short int
który zajmuje 2 bajty. Istnieje również kilka innych odmian typu całkowitego.long
lubint
ponieważ kompilator zoptymalizowałby użycie pamięci RAM lub flash według tego, co wypełnia ten rejestr, mam rację?Dzieje się tak, ponieważ operator wyjściowy traktuje to
uint8_t
jak achar
(uint8_t
zwykle jest tylko aliasem dlaunsigned char
), więc wypisuje znak z kodem ASCII (który jest najpowszechniejszym systemem kodowania znaków)5
.Zobacz np. Ten odnośnik .
źródło
signed
iunsigned
(poza zwykłym,char
który w C ++ jest tak naprawdę trzecim oddzielnym typem). Więc jeśliuint8_t
jest aliasem dlaunsigned char
(bardzo prawdopodobne), to zostanie użyte.Korzystanie z ADL (wyszukiwanie nazw zależnych od argumentów):
wynik:
Możliwy byłby również niestandardowy manipulator strumienia.
cout << +i << endl
).źródło
return std::is_signed<char>::value ? os << static_cast<int>(c) : os << static_cast<unsigned int>(c);
cout
traktujeaa
jakochar
wartość ASCII,5
która jest znakiem niedrukowalnym, spróbuj typecastinguint
przed drukowaniem.źródło
operator<<()
Przeciążenia pomiędzyistream
ichar
jest funkcją trzeciego. Możesz jawnie użyć funkcji składowej, aby traktować achar
(lub auint8_t
) jakoint
.Wynik:
źródło
Jak powiedzieli inni, problem występuje, ponieważ standardowy strumień traktuje znak ze znakiem i znak bez znaku jako pojedyncze znaki, a nie jako liczby.
Oto moje rozwiązanie z minimalnymi zmianami kodu:
Dodawanie
"+0"
jest bezpieczne z dowolną liczbą, w tym zmiennoprzecinkową.W przypadku typów całkowitych zmieni typ wyniku na
int
ifsizeof(aa) < sizeof(int)
. I nie zmieni typu, jeślisizeof(aa) >= sizeof(int)
.To rozwiązanie jest również dobre do przygotowania
int8_t
do drukowania do przesyłania strumieniowego, podczas gdy inne rozwiązania nie są tak dobre:Wynik:
Rozwiązanie PS z ADL podanym przez pepper_chico i πάντα ῥεῖ jest naprawdę piękne.
źródło