Char a Signed char i unsigned char

1

Witam

Mam takie pytanie jakie są różnice miedzy tymi typami :D ? A tak w szczególności miedzy char z signed char ? i co oznacza signed ze znakiem to znaczy że co ? Char ma od -128 do 127 i signed tez wiec po co dwa typy ? i tak samo z int i tak samo z short int ? Proszę o pomoc bo tak czytam i czytam i nie mogę teraz zrozumieć :)

Pozdrawiam i czekam na solidna odpowiedź :)

1

bo domyślnie char jest signed - to nie są dwa typy, po prostu nie musisz pisać tutaj "signed"
dopiero unsigned zmienia zakres na tylko dodatni (bez znaku) - czyli zamiast -128 do 127, masz 0 do 255

6

signed char przechowuje liczby ze znakiem
unsigned char przechowuje liczby bez znaku
char to signed char lub unsigned char (w zależności od implementacji)

0

Dziękuje za wyjaśnienie unikalna_nazwa oraz lukasz1235 już wszystko jasne :) do zamknięcia.

8

Bardzo dobre pytanie :)

lukasz1235 napisał:

signed char przechowuje liczby ze znakiem
unsigned char przechowuje liczby bez znaku
char to signed char lub unsigned char (w zależności od implementacji)

W zasadzie jest to poprawnie, natomiast warto doprecyzować, że wg standardu (sprawdzałem w draftach od C1X, C++0x oraz w finalnej wersji C89) typ "char" pozwala przechować jeden dowolny znak z podstawowego zestawu znaków, do tego gwarantując, że wartość (kod) tego znaku będzie nieujemna (w C89 było użyte słowo "dodatnia"; w C++0x takowego zapewnienia nie widzę).
Czyli "char" jako tako nie jest przez standard definiowane jako typ liczbowy, natomiast "signed char" oraz "unsigned char" już tak (za draftem C++0x: [...] char, signed char, and unsigned char are three distinct types).

Jak zauważył lukasz1235, typ char zazwyczaj jest implementowany po prostu jako albo "signed char" albo "unsigned char" (kwestia na jaki kompilator / architekturę się trafi).

Również (ku mojemu zaskoczeniu) jest w standardach jasno powiedziane, że sizeof(char), sizeof(signed char) oraz sizeof(unsigned char) ma zwracać 1 bajt.

Jeśli chodzi o typy: short, short int, signed short, signed short int, int, long int, etc, to kolejno:

Pełną nazwą typu jest "signed char" i nie ma innych nazw.
Pełną nazwą typu jest "short int", ale można też stosować: "short", "signed short", "signed short int".
Pełną nazwą typu jest "int", ale można też stosować: "signed int" lub "signed"
Pełną nazwą typu jest "long int", ale można też stosować: "long", "signed long", "signed long int".
Pełną nazwą typu jest "long long int", ale można też stosować: "long long", "signed long long", "signed long long int"

Jeśli chodzi o typy unsigned, to jest trochę mniej wyboru:
Pełną nazwą typu jest "unsigned char" i nie ma innych nazw.
Pełną nazwą typu jest "unsigned short int", ale można też pisać: "unsigned short"
Pełną nazwą typu jest "unsigned int", ale można też pisać: "unsigned"
Pełną nazwą typu jest "unsigned long int", ale można też pisać: "unsigned long"
Pełną nazwą typu jest "unsigned long long int", ale można też pisać: "unsigned long long"

Dodam jeszcze, że typ [unsigned] long long int został dodany dopiero w nowych standardach (wcześniej go nie było).

Jeśli chodzi o wielkości, to sprawa się trochę komplikuje między C a C++. Zacznijmy od C++.

W C++ jedyne co standard mówi, to tyle, że:

  • int ma mieć wielkość natywną dla danej architektury
  • ma być spełniona następująca zależność:
    sizeof(signed char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
  • nie ma podanych konkretnych wielkości dla konkretnych typów.
    (z tego co mi się obiło o uszy to na którejś wersji Craya było 1 <= 1 <= 1 <= 1, natomiast znalazłem jedynie info o 1 <= 8 <= 8 <= 8).

W C natomiast standard podaje dodatkowo "minimalne" zakresy dla powyższych zmiennych (przez minimalne rozumiem że zmienna może mieć większy zakres, ale musi mieć przynajmniej taki jak podano):
Kolejno:
signed char: -127 (sic) do 127
short int: -32767 (sic) do 32767
int: -32767 (sic) do 32767 (sic; przypominam, że to draft c1x ;>)
long int: -2147483647 (sic) do 2147483647
long long int: -9223372036854775807 (sic) do 9223372036854775807

A jeśli chodzi o unsigned (od 0 do ...):
unsigned char: 255 (czyli 2^8 - 1)
unsigned short int: 65535 (czyli 2^16 - 1)
unsigned int: 65535 (sic) (czyli 2^16 - 1)
unsigned long int: 4294967295 (czyli 2^32 - 1)
unsigned long long int: 18446744073709551615 (czyli 2^64 - 1)

Natomiast, jeśli chodzi o konkretne zakresy, to sugeruje dla pewności sprawdzić jak bierzesz do ręki nowy kompilator/architekturę/system - czasem można się przejechać ;> (np. 64-bitowym x86 na Windowsowych kompilatorach sizeof(long) zwraca 4, a na GNU/Linux zwraca 8).

Dodam, że jeśli Ci zależy na konkretnych długościach zmiennych i chcesz być przenośny między architekturami, to warto rzucić okiem na nagłówek stdint.h w C oraz cstdint w C++ - są tam podeklarowane typy względem wielkości (chociaż bodajże różni się to między C a C++ oraz między kompilatorami / zestawami nagłówków).

0
Gynvael Coldwind napisał(a):

W zasadzie jest to poprawnie, natomiast warto doprecyzować, że wg standardu (sprawdzałem w draftach od C1X, C++0x oraz w finalnej wersji C89) typ "char" pozwala przechować jeden dowolny znak z podstawowego zestawu znaków, do tego gwarantując, że wartość (kod) tego znaku będzie nieujemna (w C89 było użyte słowo "dodatnia"; w C++0x takowego zapewnienia nie widzę).

Warto dodać, że "podstawowy zestaw znaków" oznacza zestaw znaków używany przez platformę, więc wcale nie musi to być 128 znaków ASCII.

Gynvael Coldwind napisał(a):

Również (ku mojemu zaskoczeniu) jest w standardach jasno powiedziane, że sizeof(char), sizeof(signed char) oraz sizeof(unsigned char) ma zwracać 1 bajt.

Przy czym ten jeden bajt nie musi oznaczać ośmiu bitów. C/C++ sam sobie definiuje, ile wynosi jeden bajt, więc tak naprawdę jeden char może zajmować np. 16 bitów, czyli de facto dwa "normalne" bajty. Liczba bitów zajmowanych przez char jest możliwa do odczytania przez makro CHAR_BIT.

Gynvael Coldwind napisał(a):

Jeśli chodzi o wielkości, to sprawa się trochę komplikuje między C a C++. Zacznijmy od C++.

W C++ jedyne co standard mówi, to tyle, że:

  • int ma mieć wielkość natywną dla danej architektury
  • ma być spełniona następująca zależność:
    sizeof(signed char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
  • nie ma podanych konkretnych wielkości dla konkretnych typów.
    (z tego co mi się obiło o uszy to na którejś wersji Craya było 1 <= 1 <= 1 <= 1, natomiast znalazłem jedynie info o 1 <= 8 <= 8 <= 8).

Jest jeszcze podane, że dla char, signed char i unsigned char sizeof zwraca jedynkę (ale o tym pisałeś już wcześniej). Nie wiem, jak jest w C++11, ale wcześniej był wymóg, aby typy podstawowe zajmowały rozmiar będący wielokrotnością typu char. Dokładnego paragrafu nie przytoczę, ale gdzieś w standardzie to było.

0

Witam mam pytanie. Potrzebuję obliczyć dużo większa liczbę niż unsigned long long(uzywam xcode i pisze w c). Jak to zrobić ? Czy istnieje możliwość żeby liczba składała się z kilku milionów cyfr ?

1

@Anonym
W sumie to mogłeś nowy temat założyć, albo jeszcze lepiej, poszperać po forum. Jestem przekonany, że ten temat był poruszany wiele razy na forum.

W każdym razie, tak, da się to zrobić, ale musisz albo użyć odpowiedniego liba, albo samemu sobie to oprogramować.
Z libów rzuć okiem na libgmp: http://gmplib.org/
A jeśli chodzi o oprogramowanie tego samemu, to najprostasza wersja zakłada implementacje dodawania/możenia/etc pisemnego w C/C++. Rzuć okiem np. na mój post w tym temacie: http://www.uw-team.org/forum/viewtopic.php?p=16313#p16313 (+ dwa posty niżej jest kod). No i jak pisałem, poszperaj po 4p, jestem pewien że temat był już poruszany wielokrotnie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1