2010-07-01 11 views
11

widzę, że ludzie często piszą kod C, takie jak:W C są malloc (256) i malloc (sizeof (char) * 256) równoważne?

char *ptr = malloc(sizeof(char)*256); 

Czy to naprawdę konieczne? Norma mówi, że sizeof(char)==1 z definicji, więc nie ma to sensu, po prostu napisać:

char *ptr = malloc(256); 

Dzięki, Boda Cydo.

+1

Zobacz: http://stackoverflow.com/questions/2215445/are-there-mines-where-sizeofchar-1 – Saul

+2

Warto również zauważyć, że operator sizeof() jest oceniany w czasie kompilacji, więc nie ma wydajności środowiska wykonawczego hit to using sizeof(). (Z wyjątkiem przypadku, gdy długość tablicy jest określona w czasie wykonywania, ale nie jest to użyty przykład.) – poundifdef

+0

Dlaczego nie calloc? – luiscubal

Odpowiedz

21

Tak, C definiuje na 1, zawsze (a także C++).

Niemniej jednak, zgodnie z ogólną zasadą, radzę coś takiego:

char *ptr = malloc(256 * sizeof(*ptr)); 

ten sposób, gdy twój szef mówi coś w stylu: „Oh, BTW właśnie dostał zlecenie od Chin więc musimy obsługiwać wszystkie trzy chińskie alfabetów ASAP”, można zmienić go na adres:

wchar_t *ptr // ... 

a reszta może pozostać taka sama. Biorąc pod uwagę, że będziesz mieć około 10 milionów bólów głowy próbujących poradzić sobie z i18n nawet w połowie drogi, wyeliminowanie nawet kilku jest warte zachodu. Oczywiście zakłada to, że twoje numery są naprawdę przeznaczone do przechowywania znaków - jeśli to tylko jakiś surowy bufor i naprawdę potrzebujesz 256 bajtów przestrzeni dyskowej, niezależnie od tego, ile (z kilku) znaków może być, prawdopodobnie powinieneś trzymać się z malloc(256) i być z nim.

+0

huh to sprytnie. wiem sizeof (* type) działało "zgodnie z oczekiwaniami" – poundifdef

+2

@rascher: Nie ma tam 'sizeof (* type)' 'ptr' nie jest typem.Jest to zmienna wskaźnikowa – AnT

+1

@rascher: Tylko dla wyjaśnienia, możesz użyj albo 'sizeof (type)' lub 'sizeof (expression)'. W drugim przypadku kompilator dedukuje typ wyrażenia, ale samo wyrażenie jest * nie * ocenione, więc nie musi zawierać poprawnych wartości (np. który wydaje się wyłuskać wartość zerową lub uni wskaźnik nitializowany jest nadal w porządku). –

4

Są one równoważne, ale dobrze jest zachować spójność. Uczyni to również bardziej wyraźnym, więc oczywiste jest, co masz na myśli. Jeśli typ ulega zmianie, łatwiej jest znaleźć kod, który należy zaktualizować.

1

Tak, są one równoważne technicznie. To tylko kwestia stylu - używanie każdej alokacji sprawia, że ​​mniej prawdopodobne jest, że ją przegapisz, kiedy naprawdę jej potrzebujesz.

4

Może to być prawda, ale dotyczy to tylko tego konkretnego przypadku: char.

Osobiście uważam, że to dobry formularz do korzystania z formularza malloc(sizeof(char) * 256), ponieważ ktoś zmieniający typ lub kopiujący kod do podobnego celu z innym typem może pominąć subtelności tego przypadku.

+0

+1 dla podczas kopiowania kodu. – Cam

+0

' sizeof (char) * 256' nie pomaga, jeśli ktoś zmienia typ; masz na myśli 'sizeof * ptr * 256'? –

+0

@Charles, Zgoda, nadal będą musieli zmienić typ w deklaracji, ale przynajmniej wtedy będzie to wyraźne, a nie po prostu numer –

6

Problem nie powinien nawet istnieć. Należy przyjąć bardziej eleganckie idiom pisanie malloc „s jako

ptr = malloc(N * sizeof *ptr) 

tj uniknąć podając nazwę typu jak najwięcej. Nazwy typów są dla deklaracji, a nie dla instrukcji.

W ten sposób twoje malloc s zawsze będą niezależne od typu i będą wyglądały spójnie. Fakt, że mnożenie przez 1 jest zbędne, będzie mniej oczywisty (ponieważ niektórzy ludzie znajdują irytujące mnożenie przez sizeof(char)).

2

Chociaż technicznie nie ma nic złego w pisaniu sizeof(char), czyniąc to sugeruje, że autor nie zna C oraz fakt, że sizeof(char) jest zdefiniowany jako 1. W niektórych projektach Mam pracował, my rzeczywiście grep do wystąpień sizeof(char) jako wskazanie, że kod może być niskiej jakości.

Z drugiej strony, ptr = malloc(count * sizeof(*ptr)); jest bardzo przydatna dokumentacja i unikanie błędów idiom, i ma sens nawet jeśli sizeof(*ptr) to 1. Jednak to musi być poprzedzone if (count > SIZE_MAX/sizeof(*ptr)) { /* handle overflow */ } lub masz poważny błąd. Może to być szczególnie istotne w przypadku przydzielania tablic o rozmiarze wchar_t lub złożonych struktur o tej samej długości co ciąg wejściowy, na przykład podczas przekształcania ciągu znaków UTF-8 na ciąg znaków wchar_t lub budowania DFA w celu dopasowania do ciągu znaków.

+0

Warto zauważyć, że nawet w systemach, w których znak jest większy niż 8 bitów (pracowałem z takim, w którym był 16), sizeof (char) jest nadal jednym; sizeof (int) jest również w tym przypadku. Słyszałem nawet o systemach, w których sizeof (long) jest równy jeden, ponieważ "char" ma 64 bity. – supercat