Widziałem dwa style używania sizeof
do operacji związanych z pamięcią (takie jak w memset
lub malloc
):
sizeof(type)
, isizeof variable
lubsizeof(variable)
Który wolisz, czy użyłbyś kombinacji dwóch stylów i kiedy używałbyś każdego z nich? Jakie są zalety i wady każdego stylu i kiedy go używasz?
Jako przykład widzę następującą parę sytuacji, w których jeden styl pomaga, a drugi nie:
Kiedy pomylisz wskaźnik pośredni wskaźnika:
type *var;
...
memset(var, 0, sizeof var); /* oops */
Kiedy typ się zmienia:
new_type var; /* changed from old_type to new_type */
...
memset(&var, 0, sizeof(old_type)); /* oops */
c
coding-style
congusbongus
źródło
źródło
array
rzeczywiście jest tablicą C, tosizeof(array)
zwraca liczbę bajtów wymaganą do przechowywania elementów tablicy . Jeśliarray
jest wskaźnikiem do pierwszego elementu zepsutej tablicy C, oznacza to, że instrukcja jest przechowywana. Przekazanie tablicy C jako argumentu funkcji powoduje, że wygląda ona jak wskaźnik w funkcji - wszystkie informacje potwierdzające, że była to tablica, podobnie jak jej rozmiar, są tracone. Właśnie dlatego się rozkłada . Wrong 2: „Tablice w rzeczywistości nie istnieją w C; ... po prostu cukier składniowy dla wskaźników”.Preferowane jest (jak zawsze) odzwierciedlenie twojego zamiaru tak bezpośrednio, jak to możliwe.
Czy zamiar działa w oparciu o pamięć istniejącej zmiennej? Jeśli tak, to użyj
sizeof(variable)
, ponieważ pokazuje to tak dokładnie, jak to możliwe, że zależy ci na pamięci samej zmiennej.Czy zamierzasz wykonać jakieś obliczenia na typie, na przykład w celu ustalenia, ile pamięci należy przydzielić dla nowej instancji? Jeśli tak, użyj
sizeof(type)
.To znaczy wolę
koniec
ponieważ ten drugi przypadek wygląda na to, że próbujesz uzyskać dostęp do zmiennej, która jeszcze nie istnieje.
Z drugiej strony wolę
koniec
ponieważ intencją jest oczywiście wypełnienie zera zawartości zmiennej, więc jest to zmienna, przeciwko której powinniśmy działać. Próba użycia metadanych typu po prostu dezorientuje, tutaj.
źródło
void *
są one automatycznie rzutowane na inne typy wskaźników, co jest błędne.Wolałbym znacznie
sizeof(type)
więcejsizeof variable
. Mimo, że zmusza do bardziej martwić o rodzaju i dokonać więcej zmian, to pomoże Ci uniknąć błędów wskaźnik zadnie, które zaliczają się do najczęstszych przyczyn błędów w C .Nie martwiłbym się tak bardzo błędami, w których
sizeof(type)
zmienia się typ ; za każdym razem, gdy zmieniasz typ zmiennej, powinieneś wykonać szybkie skanowanie, aby zobaczyć, gdzie ta zmienna jest używana i czy musisz zmienić dowolnesizeof(type)
instrukcje. Mimo że zawsze istnieje szansa, że to się nie powiedzie, ryzyko jest znacznie mniejsze niż w przypadku błędów pośrednich wskaźnika.Jedną z zalet
sizeof variable
jest dla tablic, ale w praktyce odkryłem, że przekazywanie tablic jako par pierwsza / len jest znacznie bardziej powszechne (w takim przypadku wystarczy użyć długości), a także bardzo łatwo jest pomylić rozmiar z powodu zanik tablicy / wskaźnika, jak w tym przykładzie:źródło
sizeof var
; jeśli to wskaźnik, tosizeof *var
. Jest to również coś, co ludzie mogą pomylić, a kompilator chętnie to zrobi bez narzekań. Twierdzę, że te błędy są znacznie trudniejsze do wykrycia i są częstsze niż błędy wsizeof(type)
formularzu.C
, kod C jest bardziej pouczający niż kod C ++mat3_t::mat3_t(...)
.Celem jest usunięcie nadmiarowości. Jeśli użyjesz sizeof do operacji związanej ze zmienną, to oczywiście odzwierciedlisz to w sizeof. Tak, możesz zepsuć się jak w pierwszym przykładzie, ale lekarstwem nie jest użycie typu, ale * var, poprawnie dopasowane do celu.
Aby złagodzić takie problemy, zwykle używa się makr, szablonów i podobnych narzędzi przeszkolonych w zakresie użycia, a nie nagich rozmiarów.
Zobacz moje makro CLEAR, które jest używane wyłącznie zamiast nagiego memsetu. Zapisałem mój tyłek kilka razy w przypadku literówki pośredniej lub gdy zawartość strukturalna pobierała wektor lub ciąg ...
źródło
Logika biznesowa określa twój wybór.
Jeśli twój kod odnosi się do konkretnej zmiennej i bez tej zmiennej twój kod nie ma sensu - wybierz
sizeof(var)
Jeśli kodujesz dotyczy zestawu zmiennych określonego typu - wybierz
sizeof(type)
. Zwykle jest to potrzebne, jeśli masztypedef
definicję wielu zmiennych, które przetwarzasz inaczej w zależności od ich typu (np. Serializacja). Możesz nie wiedzieć, która z tych zmiennych pozostanie w przyszłych wersjach kodu, więc wybór typu jako argumentu jest logicznie poprawny. Nawet ich zmianatypedef
nie wpłynie na rozmiar linii.źródło
W zależności od celu rozmiar (zmienny) może być najlepszym rozwiązaniem. W ten sposób możesz zmienić typ zmiennej, jeśli to konieczne, bez poprawiania wszystkich pozycji dla tego typu. Ale znowu zależy to od twojego celu.
źródło