W tej kwestii , ktoś sugerowane w komentarzu , że powinienem nie rzucać wynik malloc
, czyli
int *sieve = malloc(sizeof(int) * length);
zamiast:
int *sieve = (int *) malloc(sizeof(int) * length);
Dlaczego miałoby tak być?
W tej kwestii , ktoś sugerowane w komentarzu , że powinienem nie rzucać wynik malloc
, czyli
int *sieve = malloc(sizeof(int) * length);
zamiast:
int *sieve = (int *) malloc(sizeof(int) * length);
Dlaczego miałoby tak być?
NULL
. (prawdopodobnie dlatego wprowadzono C ++nullptr
: C ++ nie zezwala na żadne niejawne rzutowania wskaźnika)Odpowiedzi:
Nie ; Państwo nie rzucać wynik, ponieważ:
void *
w tym przypadku jest automatycznie i bezpiecznie promowane na dowolny inny typ wskaźnika.<stdlib.h>
. Może to powodować awarie (lub, co gorsza, nie powodować awarii aż do później w jakiejś zupełnie innej części kodu). Zastanów się, co się stanie, jeśli wskaźniki i liczby całkowite będą różnej wielkości; wtedy ukrywasz ostrzeżenie, przesyłając, i możesz stracić fragmenty zwracanego adresu. Uwaga: od C99 funkcje niejawne zniknęły z C i ten punkt nie jest już istotny, ponieważ nie ma automatycznego założenia, że funkcje niezadeklarowane zwracająint
.Jako wyjaśnienie zauważ, że powiedziałem „nie rzucasz”, a nie „nie musisz rzucać”. Moim zdaniem nie można dołączyć obsady, nawet jeśli masz rację. Po prostu nie ma z tego żadnych korzyści, ale wiązka potencjalnych zagrożeń, w tym obsada wskazuje, że nie wiesz o ryzyku.
Zauważ też, jak zauważają komentatorzy, że powyższe mówi o prostym C, a nie C ++. Bardzo mocno wierzę w C i C ++ jako osobne języki.
Aby dodać dalej, kod niepotrzebnie powtarza informacje o typie (
int
), które mogą powodować błędy. Lepiej jest usunąć odwołanie do wskaźnika używanego do przechowywania wartości zwracanej, aby „zablokować” oba razem:To również przesuwa
length
przód do przodu w celu zwiększenia widoczności i upuszcza zbędne nawiasysizeof
; one są potrzebne tylko wtedy, gdy argument jest nazwą typu. Wydaje się, że wiele osób nie wie (lub ignoruje) to, co sprawia, że ich kod jest bardziej szczegółowy. Pamiętaj:sizeof
nie jest funkcją! :)Podczas gdy przejście
length
do przodu może zwiększyć widoczność w niektórych rzadkich przypadkach, należy również zwrócić uwagę, że w ogólnym przypadku lepiej jest napisać wyrażenie jako:Ponieważ zachowanie
sizeof
pierwszego, w tym przypadku zapewnia, że mnożenie odbywa się co najmniej zsize_t
matematyki.Porównaj:
malloc(sizeof *sieve * length * width)
vs.malloc(length * width * sizeof *sieve)
drugi może przepełnić,length * width
kiedywidth
ilength
są mniejsze niżsize_t
.źródło
int x = (int) 12;
po to, aby wszystko było jasne?(int)12
nie jest porównywalny.12
jestint
, obsada robi po prostu nic. Retval odmalloc()
Isvoid *
, nie typ wskaźnik do lanego. (Jeśli nie jestvoid *
. Więc analogia do(int)12
tego, o(void*)malloc(…)
czym nikt nie dyskutuje.)W C nie musisz rzutować wartości zwracanej na
malloc
. Wskaźnik zwrócony przez voidmalloc
jest automatycznie konwertowany na poprawny typ. Jeśli jednak chcesz, aby Twój kod skompilował się przy użyciu kompilatora C ++, niezbędny jest rzut. Preferowaną alternatywą wśród społeczności jest użycie następujących opcji:co dodatkowo uwalnia cię od konieczności martwienia się o zmianę prawej strony wyrażenia, jeśli zmienisz typ
sieve
.Obsady są złe, jak zauważyli ludzie. Szczególnie rzutki.
źródło
malloc(length * sizeof *sieve)
to wyglądasizeof
na zmienną - więc myślę, żemalloc(length * sizeof(*sieve))
jest bardziej czytelna.malloc(length * (sizeof *sieve))
jeszcze bardziej czytelny. MOIM ZDANIEM.()
marginesie problem Michaela Andersona , zauważ, że twój sugerowany styl zmienił kolejność., Zastanów się, kiedy obliczana jest liczba elementówlength*width
, zachowującsizeof
pierwszy w tym przypadku, upewniając się, że mnożenie odbywa się co najmniej zsize_t
matematyki. Porównajmalloc(sizeof( *ptr) * length * width)
vs.malloc(length * width * sizeof (*ptr))
- 2. może przepełnić,length*width
kiedywidth,length
są mniejsze typy, któresize_t
.malloc(sizeof *sieve * length)
static_cast>()
(lubreinterpret_cast<>()
) nie jest kompatybilny z żadnym dialektem C.Państwo nie rzucać, ponieważ:
type *
porównaniu dotype **
.#include
się znaleźć odpowiedniego pliku nagłówkowego, pomija las drzew . To tak samo, jak powiedzenie „nie przejmuj się faktem, że nie poprosiłeś kompilatora, aby narzekał na brak prototypów - to nieznośne stdlib.h jest PRAWDZIWĄ ważną rzeczą do zapamiętania!”malloc()
błędy są wykrywane znacznie szybciej, gdy jest obsada. Podobnie jak w przypadku stwierdzeń, adnotacje ujawniające zamiar zmniejszają liczbę błędów.źródło
.c
/.cpp
do kompilacji, ponieważ oba są bardzo przydatne, ale jednym z przypadków jest dodanie obsługi C ++throw
po kompilacji za pomocą kompilatora C ++ (alereturn -1;
po kompilacji za pomocą kompilatora C lub cokolwiek innego).malloc
wywołaniu:char **foo = malloc(3*sizeof(*foo));
jeśli całkiem w pełni dowód: 3 wskaźniki do wskaźników char. następnie zapętlić i zrobićfoo[i] = calloc(101, sizeof(*(foo[i])));
. Przydziel tablicę 101 znaków, starannie zainicjowanych zerami. Nie potrzeba obsady. zmień deklarację naunsigned char
inny typ, jeśli o to chodzi, i nadal jesteś dobrystruct Zebra *p; ... p=malloc(sizeof struct Zebra);
, malloc nie może uniknąć powielania informacji o typie p, ale ani kompilator, ani kontrola kodu lokalnego nie wykryłyby żadnego problemu, gdyby jeden typ się zmienił, a drugi nie. Aby zmienić kodp=(struct Zebra*)malloc(sizeof struct Zebra);
i kompilator skrzek jeśli typ obsada nie pasujep
, a lokalna kontrola ujawni ...Jak powiedzieli inni, nie jest potrzebny w C, ale w C ++. Jeśli uważasz, że zamierzasz skompilować kod C za pomocą kompilatora C ++, z jakichkolwiek powodów możesz użyć makra, na przykład:
W ten sposób możesz nadal pisać w bardzo kompaktowy sposób:
i skompiluje się dla C i C ++.
źródło
new
w definicji C ++?new
, musisz używać,delete
a jeśli używaszmalloc()
, musiszfree()
. Nigdy ich nie mieszaj.NEW
jest prawdopodobnie złym pomysłem, ponieważ zasób nigdy nie jest zwracany za pomocądelete
(lubDELETE
), więc miksujesz słownictwo. Zamiast tego nazywanie goMALLOC
, a raczejCALLOC
w tym przypadku, miałoby większy sens.Z Wikipedii :
Chociaż metoda malloc bez rzutowania jest preferowaną metodą i wybierają ją najbardziej doświadczeni programiści , powinieneś użyć dowolnej z tych opcji, aby mieć świadomość problemów.
tzn .: jeśli musisz skompilować program C jako C ++ (chociaż jest to osobny język), musisz rzutować wynik użycia
malloc
.źródło
malloc()
” może pomóc deweloperowi w identyfikowaniu niespójności przy zmianie typu, jeśli powinien zmienić się typ docelowego wskaźnika, szczególnie jeśli wskaźnik jest zadeklarowany z dala od wywołania ”? Czy możesz podać przykład?p = malloc(sizeof(*p) * count)
idiom automatycznie rozpoznaje zmiany typu, więc nie musisz otrzymywać ostrzeżeń i nic nie zmieniać. Nie jest to więc prawdziwa zaleta w porównaniu z najlepszą alternatywą dla nie rzucania.W C można niejawnie przekonwertować
void
wskaźnik na dowolny inny wskaźnik, więc rzutowanie nie jest konieczne. Użycie jednego może zasugerować przypadkowemu obserwatorowi, że istnieje jakiś powód, dla którego jest on potrzebny, co może wprowadzać w błąd.źródło
Nie rzutujesz wyniku malloc, ponieważ powoduje to niepotrzebny bałagan w kodzie.
Najczęstszym powodem, dla którego ludzie rzucają wynik malloc, jest to, że nie są pewni, jak działa język C. To znak ostrzegawczy: jeśli nie wiesz, jak działa dany mechanizm językowy, nie zgaduj. Sprawdź to lub zapytaj o Przepełnienie stosu.
Niektóre komentarze:
Wskaźnik pustki można przekonwertować na / z dowolnego innego typu wskaźnika bez wyraźnego rzutowania (C11 6.3.2.3 i 6.5.16.1).
C ++ nie zezwala jednak na niejawne rzutowanie między
void*
innym typem wskaźnika. Tak więc w C ++ obsada byłaby poprawna. Ale jeśli programujesz w C ++, powinieneś używać,new
a nie malloc (). I nigdy nie powinieneś kompilować kodu C za pomocą kompilatora C ++.Jeśli potrzebujesz obsługiwać zarówno C, jak i C ++ przy użyciu tego samego kodu źródłowego, użyj przełączników kompilatora, aby zaznaczyć różnice. Nie próbuj dopasowywać obu standardów językowych za pomocą tego samego kodu, ponieważ nie są one kompatybilne.
Jeśli kompilator C nie może znaleźć funkcji, ponieważ zapomniałeś dołączyć nagłówek, pojawi się błąd kompilatora / linkera. Więc jeśli zapomniałeś dołączyć
<stdlib.h>
to nie jest biggie, nie będziesz w stanie zbudować swojego programu.W starożytnych kompilatorach zgodnych z wersją standardu, która ma ponad 25 lat, zapomnienie o dołączeniu
<stdlib.h>
spowodowałoby niebezpieczne zachowanie. Ponieważ w tym starożytnym standardzie funkcje bez widocznego prototypu domyślnie przekształcały typ zwracany naint
. Bezpośrednie przesłanie wyniku z malloc ukryłoby ten błąd.Ale to naprawdę nie jest problem. Nie używasz 25-letniego komputera, więc dlaczego miałbyś używać 25-letniego kompilatora?
źródło
W C otrzymujesz niejawną konwersję z
void *
dowolnego innego wskaźnika (danych).źródło
Rzucanie wartości zwracanej przez
malloc()
nie jest teraz konieczne, ale chciałbym dodać jeden punkt, który wydaje się, że nikt nie zauważył:W dawnych czasach, to znaczy, zanim ANSI C zapewnia
void *
ogólny typ wskaźników,char *
jest typem takiego użycia. W takim przypadku rzutowanie może wyłączyć ostrzeżenia kompilatora.Odniesienie: C FAQ
źródło
Dodając moje doświadczenie, studiując inżynierię komputerową, widzę, że dwaj lub trzej profesorowie, których pisałem w C, zawsze rzucali malloc, jednak ten, o który prosiłem (z ogromnym CV i zrozumieniem C) powiedział mi, że jest to absolutnie niepotrzebne, ale były tylko absolutnie specyficzne i pozwalały uczniom wejść w mentalność absolutnej specyficzności. Zasadniczo rzutowanie nie zmieni niczego w sposobie działania, robi dokładnie to, co mówi, przydziela pamięć, a rzutowanie nie wpływa na to, dostajesz tę samą pamięć, a nawet jeśli przypadkowo rzucisz ją na coś innego (i jakoś unikniesz kompilatora błędy) C uzyska do niego dostęp w ten sam sposób.
Edycja: Casting ma pewien punkt. Kiedy używasz notacji tablicowej, wygenerowany kod musi wiedzieć, ile miejsc pamięci musi przejść, aby osiągnąć początek następnego elementu, jest to osiągane poprzez rzutowanie. W ten sposób wiesz, że dla podwójnej przewijasz 8 bajtów do przodu, podczas gdy dla int masz 4, i tak dalej. Dlatego nie ma to żadnego efektu, jeśli używasz notacji wskaźnikowej, w notacji tablicowej staje się to konieczne.
źródło
p = malloc(sizeof *p * n);
jest to takie proste i lepsze.Rzucanie wyników nie jest obowiązkowe
malloc
, ponieważ zwracavoid*
, avoid*
można wskazać dowolny typ danych.źródło
Wskaźnik pustki jest ogólnym wskaźnikiem obiektu, a C obsługuje niejawną konwersję z typu wskaźnika pustki na inne typy, więc nie ma potrzeby jawnego rzutowania go.
Jeśli jednak chcesz, aby ten sam kod działał idealnie kompatybilny na platformie C ++, która nie obsługuje niejawnej konwersji, musisz wykonać rzutowanie czcionek, więc wszystko zależy od użyteczności.
źródło
malloc
i przyjaciół w C ++ jest dobrym znakiem ostrzegawczym, że zasługuje na szczególną uwagę (lub ponowne napisanie w C).void *
, dlatego nievoid *
są wystarczające, aby dobrze przechowywać wskaźnik funkcji.Tak mówi Podręcznik GNU C Library Reference :
I rzeczywiście norma ISO C11 (p347) mówi:
źródło
Zwrócony typ jest nieważny *, który można rzutować na pożądany typ wskaźnika danych, aby być dereferencyjnym.
źródło
void*
można rzutować na żądany typ, ale nie ma takiej potrzeby, ponieważ zostanie on automatycznie przekonwertowany. Dlatego obsada nie jest konieczna, a wręcz niepożądana z powodów wymienionych w odpowiedziach na najwyższe noty.W języku C wskaźnik pustki można przypisać do dowolnego wskaźnika, dlatego nie należy używać rzutowania typu. Jeśli chcesz przydzielić „bezpieczny typ”, mogę polecić następujące funkcje makr, których zawsze używam w moich projektach C:
Po ich wprowadzeniu możesz po prostu powiedzieć
W przypadku tablic niedynamicznych trzecim niezbędnym makrem funkcji jest
co sprawia, że pętle macierzy są bezpieczniejsze i wygodniejsze:
źródło
malloc()
jeden.void*
do / od wskaźnika funkcji może spowodować utratę informacji, więc „wskaźnik pustki można przypisać do dowolnego wskaźnika”, w takich przypadkach jest problemem. Przypisanie wskaźnikavoid*
odmalloc()
do dowolnego obiektu nie jest jednak problemem.do
Komentarz pętla związane z makrami z udziałem jeszcze pętlę, która zastanawia się od tytułowego pytania. Usuwam ten komentarz. Zrobię to później.To zależy od języka programowania i kompilatora. Jeśli używasz
malloc
w C, nie ma potrzeby wpisywania rzutowania, ponieważ będzie on automatycznie wpisywać rzutowanie. Jeśli jednak używasz C ++, powinieneś wpisać cast, ponieważmalloc
zwrócivoid*
typ.źródło
Ludzie przyzwyczajeni do GCC i Clanga są rozpieszczani. Tam nie jest tak dobrze.
Przez lata byłem przerażony niesamowicie starzejącymi się kompilatorami, których musiałem używać. Często firmy i menedżerowie przyjmują bardzo konserwatywne podejście do zmiany kompilatorów i nawet nie testują czy nowy kompilator (z lepszą zgodnością standardów i optymalizacją kodu) będzie działał w ich systemie. Praktyczna rzeczywistość dla pracujących programistów polega na tym, że kiedy piszesz kod, musisz zakryć swoje bazy i, niestety, rzucanie mallocami jest dobrym nawykiem, jeśli nie możesz kontrolować, który kompilator może zostać zastosowany do twojego kodu.
Sugerowałbym również, że wiele organizacji stosuje własne standardy kodowania i że to powinna być metoda, którą ludzie zastosują, jeśli zostanie ona zdefiniowana. Wobec braku wyraźnych wskazówek staram się raczej gromadzić wszędzie, niż niewolnicze przestrzeganie standardu.
Argument, że zgodnie z obecnymi standardami nie jest konieczny, jest całkiem aktualny. Ale ten argument pomija praktyczne aspekty prawdziwego świata. Nie kodujemy w świecie rządzonym wyłącznie standardami dnia, ale praktycznością tego, co lubię nazywać „rzeczywistością lokalnego zarządzania”. I to jest wygięte i pokręcone bardziej niż kiedykolwiek czasoprzestrzeń. :-)
YMMV.
Często myślę o rzucaniu malloca jako operacji obronnej. Nie ładna, nie idealna, ale ogólnie bezpieczna. (Szczerze mówiąc, jeśli nie podałeś stdlib.h, masz o wiele więcej problemów niż rzucanie malloc!).
źródło
Włączyłem rzutowanie po prostu, aby pokazać dezaprobatę dla brzydkiej dziury w systemie tekstowym, co pozwala kompilować kod, taki jak poniższy fragment kodu, bez diagnostyki, mimo że żadne rzutowania nie są używane do spowodowania złej konwersji:
Chciałbym, żeby to nie istniało (i nie ma w C ++), więc rzuciłem. Reprezentuje mój gust i moją politykę programistyczną. Nie tylko rzucam wskaźnik, ale skutecznie, rzucam kartę do głosowania i wyrzucam demony głupoty . Jeśli nie mogę tak naprawdę wyrzucić głupoty , to przynajmniej pozwólcie mi wyrazić życzenie gestem protestu.
W rzeczywistości dobrą praktyką jest owijanie
malloc
(i znajomych) funkcjami, które zwracająunsigned char *
, i zasadniczo nigdy nie należy ich używaćvoid *
w kodzie. Jeśli potrzebujesz ogólnego wskaźnika do dowolnego obiektu, użyj achar *
lubunsigned char *
i rzutuj w obu kierunkach. Jedną z relaksacji, na którą można sobie pozwolić, może być używanie funkcji takich jakmemset
imemcpy
bez rzutów.Na temat odlewów i kompatybilności C ++, jeśli napisać kod tak, że kompiluje jako ++ (w takim przypadku zarówno C i C muszą rzutować wartości zwracanej
malloc
podczas przypisywania go do czegoś innego niżvoid *
), można zrobić bardzo pomocny rzecz dla siebie: możesz używać makr do rzutowania, które tłumaczą rzutowania w stylu C ++ podczas kompilacji jako C ++, ale redukują się do rzutowania C podczas kompilacji jako C:Jeśli zastosujesz się do tych makr, proste
grep
przeszukanie bazy kodu dla tych identyfikatorów pokaże Ci, gdzie znajdują się wszystkie Twoje rzutowania, dzięki czemu możesz sprawdzić, czy któryś z nich jest niepoprawny.Następnie, jeśli będziesz regularnie kompilować kod w C ++, wymusi to użycie odpowiedniej obsady. Na przykład, jeśli używasz
strip_qual
tylko w celu usunięciaconst
lubvolatile
, ale zmiany programu w taki sposób, że konwersja typu jest obecnie zaangażowany, dostaniesz diagnostyczny i trzeba będzie użyć kombinacji odlewów, aby uzyskać żądaną konwersję.Aby pomóc Ci w przestrzeganiu tych makr, kompilator GNU C ++ (nie C!) Ma piękną funkcję: opcjonalną diagnostykę, która jest generowana dla wszystkich wystąpień rzutowań w stylu C.
Jeśli Twój kod C kompiluje się jako C ++, możesz użyć tej
-Wold-style-cast
opcji, aby znaleźć wszystkie wystąpienia(type)
składni rzutowania, które mogą wkraść się do kodu, i śledzić tę diagnostykę, zastępując go odpowiednim wyborem spośród powyższych makr (lub połączenie, jeśli to konieczne).Takie traktowanie konwersji jest największym pojedynczym samodzielnym technicznym uzasadnieniem pracy w „Clean C”: połączonym dialekcie C i C ++, co z kolei technicznie uzasadnia rzutowanie wartości zwracanej
malloc
.źródło
Najlepszą rzeczą do zrobienia przy programowaniu w C, gdy tylko jest to możliwe:
-Wall
i napraw wszystkie błędy i ostrzeżeniaauto
-Wall
i-std=c++11
. Napraw wszystkie błędy i ostrzeżenia.Ta procedura pozwala wykorzystać ścisłe sprawdzanie typu C ++, zmniejszając w ten sposób liczbę błędów. W szczególności ta procedura zmusza Cię do włączenia
stdlib.h
lub otrzymasza także zmusza cię do rzucenia wyniku
malloc
lub dostanieszlub jaki jest Twój typ docelowy.
Jedyne zalety pisania w C zamiast C ++, jakie mogę znaleźć, to
Zauważ, że drugie minusy powinny w idealnym przypadku zniknąć, gdy użyjesz podzbioru wspólnego dla C razem ze statyczną cechą polimorficzną.
Dla tych, którzy uznają surowe reguły C ++ za niewygodne, możemy użyć funkcji C ++ 11 z wnioskowanym typem
źródło
gcc -c c_code.c
), Kod C ++ jako C ++ (np.g++ -c cpp_code.cpp
), A następnie połączyć je ze sobą (np.gcc c_code.o cpp_code.o
lub odwrotnie w zależności od zależności projektu). Teraz nie powinno być powodu, aby pozbawiać się jakichkolwiek przyjemnych cech któregokolwiek języka ...p = malloc(sizeof(*p));
, co nie wymaga zmiany w pierwszej kolejności, jeślip
zmieni się nazwa innego typu. Proponowaną „zaletą” rzutowania jest to, że pojawia się błąd kompilacji, jeślip
jest to zły typ, ale jeszcze lepiej, jeśli po prostu działa.Nie, nie rzucasz wyniku
malloc()
.Ogólnie rzecz biorąc, nie przesyłasz do ani z
void *
.Typowym powodem, dla którego się tego nie robi, jest brak
#include <stdlib.h>
niezauważenia. Już od dawna nie jest to problemem, ponieważ C99 sprawił, że niejawne deklaracje funkcji są nielegalne, więc jeśli twój kompilator jest zgodny co najmniej z C99, otrzymasz komunikat diagnostyczny.Ale istnieje znacznie silniejszy powód, aby nie wprowadzać niepotrzebnych rzutów wskaźnika:
W C rzutowanie wskaźnika prawie zawsze jest błędem . Wynika to z następującej zasady ( § 6.5 p7 w N1570, najnowszy projekt dla C11):
Jest to również znane jako ścisła zasada aliasingu . Zatem poniższy kod jest niezdefiniowanym zachowaniem :
I, czasem zaskakujące, są również następujące kwestie:
Czasami nie trzeba wskaźniki obsady, ale biorąc pod uwagę ścisłe reguły aliasingu , trzeba być bardzo ostrożnym z nim. Tak więc każde wystąpienie wskaźnika rzuconego w kodzie jest miejscem, w którym należy dokładnie sprawdzić jego poprawność . Dlatego nigdy nie piszesz niepotrzebnego rzutowania wskaźnika.
tl; dr
W skrócie: Ponieważ w C każde wystąpienie rzutowania wskaźnika powinno podnieść czerwoną flagę dla kodu wymagającego specjalnej uwagi, nigdy nie należy pisać niepotrzebnych rzutowań wskaźnika.
Notatki dodatkowe:
Są przypadki, w których naprawdę potrzebujesz rzutowania
void *
, np. Jeśli chcesz wydrukować wskaźnik:Obsada jest tutaj niezbędna, ponieważ
printf()
jest funkcją wariadyczną, więc niejawne konwersje nie działają.W C ++ sytuacja jest inna. Rzutowanie typów wskaźników jest dość powszechne (i poprawne) w przypadku obiektów klas pochodnych. Dlatego ma sens, że w C ++ konwersja do iz nie
void *
jest niejawna. C ++ ma cały zestaw różnych smaków castingu.źródło
Wolę robić obsadę, ale nie ręcznie. Moim ulubionym jest używanie
g_new
ig_new0
makra z glib. Jeśli glib nie jest używany, dodałbym podobne makra. Te makra zmniejszają powielanie kodu bez uszczerbku dla bezpieczeństwa typu. Jeśli pomylisz się w typie, otrzymasz niejawne rzutowanie między wskaźnikami nie będącymi nieważnymi, co spowoduje ostrzeżenie (błąd w C ++). Jeśli zapomnisz dołączyć nagłówek, który definiujeg_new
ig_new0
, otrzymasz błąd.g_new
ig_new0
oba przyjmują te same argumenty, w przeciwieństwie domalloc
tego , że bierze mniej argumentów niżcalloc
. Wystarczy dodać,0
aby uzyskać pamięć inicjowaną zerem. Kod można skompilować za pomocą kompilatora C ++ bez zmian.źródło
Przesyłanie dotyczy tylko C ++, a nie C. Jeśli używasz kompilatora C ++, lepiej zmień go na kompilator C.
źródło
Koncepcja wskaźnika pustki polega na tym, że można go rzutować na dowolny typ danych, dlatego malloc zwraca wartość pustą. Musisz także pamiętać o automatycznym rzutowaniu czcionek. Rzucanie wskaźnika nie jest więc obowiązkowe, ale musisz to zrobić. Pomaga w utrzymaniu kodu w czystości i pomaga w debugowaniu
źródło
Wskaźnik pustki jest wskaźnikiem ogólnym, a C obsługuje niejawną konwersję z typu wskaźnika pustki na inne typy, więc nie ma potrzeby jawnego jego rzutowania.
Jeśli jednak chcesz, aby ten sam kod działał idealnie kompatybilny na platformie C ++, która nie obsługuje niejawnej konwersji, musisz wykonać rzutowanie czcionek, więc wszystko zależy od użyteczności.
źródło
Jak już wspomniano, nie jest to konieczne dla C, ale dla C ++.
Dołączenie rzutowania może umożliwić kompilację programu lub funkcji C jako C ++.
W C nie jest to konieczne, ponieważ void * jest automatycznie i bezpiecznie promowany do dowolnego innego typu wskaźnika.
Jeśli jednak rzucisz, może ukryć błąd, jeśli zapomnisz dołączyć plik stdlib.h . Może to powodować awarie (lub, co gorsza, nie powodować awarii aż do później w jakiejś zupełnie innej części kodu).
Ponieważ stdlib.h zawiera prototyp dla malloc, został znaleziony. W przypadku braku prototypu dla malloc, standard wymaga, aby kompilator C zakładał, że malloc zwraca int. Jeśli nie ma rzutowania, generowane jest ostrzeżenie, gdy ta liczba całkowita jest przypisana do wskaźnika; jednak w przypadku obsady to ostrzeżenie nie jest generowane, ukrywając błąd.
źródło
Rzucanie malloc jest niepotrzebne w C, ale obowiązkowe w C ++.
Przesyłanie w C jest zbędne, ponieważ:
void *
jest automatycznie i bezpiecznie promowany do dowolnego innego typu wskaźnika w przypadku C.<stdlib.h>
. Może to powodować awarie.malloc
jest wywoływany i rzutowany.Z drugiej strony casting może zwiększyć przenośność twojego programu. tzn. pozwala kompilacji programu lub funkcji C jako C ++.
źródło
Dla mnie, weźmy do domu i wniosek jest taki, że castowanie
malloc
w C nie jest absolutnie konieczne, ale jeśli jednak rzucisz, nie będzie to miało wpływu,malloc
ponieważmalloc
nadal przydzieli ci żądane miejsce w pamięci. Innym sposobem na zabranie do domu jest powód lub jeden z powodów, dla których ludzie rzucają casting, a to pozwala im skompilować ten sam program w C lub C ++.Mogą być inne powody, ale inne, prawie na pewno, wpędzą cię w poważne kłopoty prędzej czy później.
źródło
Możesz, ale nie musisz przesyłać w C. Musisz przesyłać, jeśli ten kod jest skompilowany jako C ++.
źródło