2009-10-08 18 views
7

Podczas odpowiadania na komentarz do innej mojej odpowiedzi here, znalazłem, co myślę, że może być dziurą w standardzie C (c1x, nie sprawdziłem wcześniejszych i tak, wiem, że jest nieprawdopodobne, żebym sam wśród wszystkich mieszkańców planety znalazł błąd w standardzie). Informacje są następujące:Potencjalny problem z C standardowymi znakami malloc'ing

  1. Sekcja 6.5.3.4 ("Operator wielkości") para 2 stwierdza "The sizeof operator yields the size (in bytes) of its operand".
  2. Para 3 tej sekcji stanowi: "When applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1".
  3. Sekcja 7.20.3.3 opisuje void *malloc(size_t sz), ale wszystko to mówi: "The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate". Nie wspomina wcale o tym, jakie jednostki są używane do argumentacji.
  4. Aneks E zaczyna się od 8 to minimalna wartość dla CHAR_BIT, więc znaki mogą mieć więcej niż jeden bajt długości.

Moje pytanie jest po prostu tak:

W środowisku, w którym znak ma szerokość 16 bitów, będzie malloc(10 * sizeof(char)) przeznaczyć 10 znaków (20 bajtów) lub 10 bajtów? Punkt 1 powyżej wydaje się wskazywać na pierwszy, punkt 2 wskazuje na to drugie.

Ktoś, kto ma więcej C-standard-fu niż ja, ma na to odpowiedź?

Odpowiedz

16

W 16-bitowym char środowisku malloc(10 * sizeof(char)) przydziela 10 char s (10 bajtów), ponieważ jeżeli char wynosi 16 bitów, to architektura/realizacja definiuje bajt jak 16 bitów. A char nie jest oktetem, jest bajtem. Na starszych komputerach może być większy niż standard 8-bitowy de-facto jaki mamy dzisiaj.

Odpowiednia sekcja od standardu C następuje:

3.6 Terminy, definicje, symbole

bajt - adresowalna jednostka przechowywania danych wystarczająco duży, aby pomieścić każdy członek podstawowego zestawu znaków realizacji środowisko ...

UWAGA 2 - Bajt składa się z ciągłej sekwencji bitów, których liczba jest definiowana przez implementację.

+1

Właściwie myślę, że możesz go tam mieć. na podstawie Twojej odpowiedzi znalazłem 3.6 (w "Terminy, definicje i symbole") określające "bajt - adresowalną jednostkę pamięci danych wystarczająco dużą, aby pomieścić dowolny element podstawowego zestawu znaków środowiska wykonawczego ... UWAGA 2 - bajt składa się z ciągłej sekwencji bitów, których liczba jest definiowana przez implementację ". – paxdiablo

+0

Cholera, pomyśl o chwale i pochwałach, jakie otrzymałbym za znalezienie problemu w standardzie. No cóż, wracając do codziennej pracy :-) – paxdiablo

+0

Po raz kolejny powtarzam mantrę "Muszę dostać kopię standardów". Dodam twoje standardy do mojej odpowiedzi na kompletność. –

1

Czy jednostki "size_t sz" nie są w jakiejkolwiek adresowalnej jednostce architektury? Pracuję z DSP, którego adresy odpowiadają wartościom 32-bitowym, a nie bajtom. malloc (1) daje mi wskaźnik do 4-bajtowego obszaru.

+1

Pod względem sformułowania w standardzie C, "bajt" w tej architekturze wynosi 32 bity. Nieco mylące jest to, co standard C nazywa "bajtem", niekoniecznie odpowiada (dzisiejszemu) powszechnemu używaniu tego słowa. – caf

+1

Z tego samego powodu, gdy standardy sieciowe oznaczają "8 bitów", mówią "oktet", a nie "bajt". Tylko w kontekście detalicznym bajt jest jednoznacznie 8-bitowy, jak w "MB przepustowości", "GB pamięci RAM", "TB miejsca na dysku". –

+0

Ach, to ma sens. Sądzę, że utknęliśmy w dwuznaczności dla prawników niezwiązanych z językiem, ponieważ słowa takie jak "megaokety" lub "kibiokety" nie płyną szczególnie dobrze. – twon33

2

W standardzie C99 rygorystyczne korelacja bajtów char i wielkości obiektu znajduje się w 6.2.6.1/4 „reprezentacjami typów - ogólne”:

Wartości przechowywane w przedmiotach innych niż dla pola dowolnego innego typu obiektu składa się z n × CHAR_BIT bitów, gdzie n jest wielkością obiektu tego typu, w bajtach. Wartość może być kopiowana do obiektu typu unsigned char [n] (np. Przez memcpy); wynikowy zbiór bajtów jest nazywany reprezentacją obiektu wartości.

W standardzie C++ ten sam związek podawany jest w 3.9/2 „Types”:

każdy obiekt (innych niż podobiektu podstawy klasy) typu POD T czy obiekt przechowuje poprawną wartość typu T, leżące pod nim bajty (1.7) tworzące obiekt można skopiować do tablicy char lub unsigned char. Jeśli zawartość tablicy char lub unsigned char zostanie skopiowana z powrotem do obiektu, obiekt będzie później trzymał swoją oryginalną wartość.

W C90 tam nie wydaje się być wyraźnie wymienione jako korelację, ale między definicją bajt, definicji charakteru i definicji operatora sizeof wnioskowanie może być wykonane, że typ char jest odpowiednikiem bajtu.

Należy również zauważyć, że liczba bitów w bajcie (oraz liczba bitów w char) to implementacja zdefiniowana jako —, ściśle mówiąc, nie musi to być 8 bitów. I jedno uwaga w komentarzu gdzie indziej, że DSP zwykle mają bajty z liczbą bitów, które nie są 8.

Należy zauważyć, że IFCF RFC i standardy ogólnie (zawsze?) Używają terminu "octect" zamiast "bajtu" być jednoznacznym, że jednostki, o których mówią, mają dokładnie 8 bitów - nie więcej, nie mniej.

+0

+1. Warto wspomnieć, że standard ustawia * niższy * granica CHAR_BITS, ale nie górny. Musi mieć co najmniej 8. – paxdiablo