Werfe ich das Ergebnis von malloc?

In dieser Frage schlug jemand in einem Kommentar vor, dass ich das Ergebnis von malloc nicht casting sollte, dh

 int *sieve = malloc(sizeof(int) * length); 

eher, als:

 int *sieve = (int *) malloc(sizeof(int) * length); 

Warum sollte das der Fall sein?

Solutions Collecting From Web of "Werfe ich das Ergebnis von malloc?"

Nein ; Sie casting das Ergebnis nicht, denn:

  • Es ist unnötig, da void * in diesem Fall automatisch und sicher zu jedem anderen pointerstyp befördert wird.
  • Es fügt dem Code Unordnung hinzu, Umwandlungen sind nicht sehr einfach zu lesen (besonders wenn der pointerstyp lang ist).
  • Es lässt dich dich wiederholen, was im Allgemeinen schlecht ist.
  • Es kann einen Fehler verbergen, wenn Sie vergessen haben. Dies kann zu Abstürzen führen (oder, schlimmer noch, nicht bis zu einem späteren Zeitpunkt in einem völlig anderen Teil des Codes zum Absturz führen). Überlegen Sie, was passiert, wenn pointers und Ganzzahlen unterschiedlich groß sind; dann versteckst du eine Warnung durch das Casting und kannst Teile deiner zurückgegebenen Adresse verlieren. Anmerkung: Seit C11 sind implizite functionen aus C verschwunden, und dieser Punkt ist nicht mehr relevant, da es keine automatische Annahme gibt, dass nicht deklarierte functionen int .

Zur Klarstellung, dass ich gesagt habe “Du bist nicht”, nicht “Du musst nicht”. Meiner Meinung nach ist es ein Fehler, die Besetzung aufzunehmen, selbst wenn Sie es richtig verstanden haben. Es gibt einfach keine Vorteile, es zu tun, aber eine Reihe von potenziellen Risiken, einschließlich der Besetzung zeigt, dass Sie nicht über die Risiken wissen.

Beachten Sie auch, wie die Kommentatoren darauf hinweisen, dass das oben Gesagte gerade C und nicht C ++ betrifft. Ich glaube fest an C und C ++ als separate Sprachen.

Um weiter hinzuzufügen, wiederholt Ihr Code unnötigerweise die Typinformation ( int ), die Fehler verursachen kann. Es ist besser, den pointers, der zum Speichern des Rückgabewerts verwendet wird, zu dereferenzieren, um die beiden zusammen zu “sperren”:

 int *sieve = malloc(length * sizeof *sieve); 

Dadurch wird auch die length für eine bessere Sichtbarkeit nach vorne verschoben und die überflüssigen Klammern mit sizeof ; Sie werden nur benötigt, wenn das Argument ein Typname ist. Viele Leute scheinen dies nicht zu wissen (oder zu ignorieren), was ihren Code verständlicher macht. Denken Sie daran: sizeof ist keine function! 🙂


Während die Bewegungslänge nach vorne die Sichtbarkeit in einigen seltenen Fällen erhöhen kann , sollte man auch darauf achten, dass es im allgemeinen Fall besser ist, den Ausdruck wie folgt zu schreiben:

 int *sieve = malloc(sizeof *sieve * length); 

Da in diesem Fall die sizeof ersten sizeof wird, wird sichergestellt, dass die Multiplikation mit mindestens size_t math durchgeführt wird.

Vergleiche: malloc(sizeof *sieve * length * width) vs. malloc(length * width * sizeof *sieve) die zweite kann die length * width malloc(length * width * sizeof *sieve) wenn width und length kleiner sind als size_t .

In C müssen Sie den Rückgabewert von malloc nicht malloc . Der von malloc pointers auf void wird automatisch in den richtigen Typ konvertiert. Wenn Sie möchten, dass Ihr Code mit einem C ++ – Compiler kompiliert wird, ist jedoch eine Umwandlung erforderlich. Eine bevorzugte Alternative in der Community ist die Verwendung der folgenden:

 int *sieve = malloc(sizeof *sieve * length); 

Dadurch müssen Sie sich auch nicht mehr darum kümmern, die rechte Seite des Ausdrucks zu ändern, wenn Sie den sieve ändern.

Abgüsse sind schlecht, wie die Leute darauf hingewiesen haben. Speziell pointers wirft.

Du machst Cast, weil:

  • Es macht Ihren Code portabler zwischen C und C ++, und wie die SO-Erfahrung zeigt, behaupten sehr viele Programmierer, dass sie in C schreiben, wenn sie wirklich in C ++ schreiben (oder C plus lokale Compiler-Erweiterungen).
  • Wenn dies nicht möglich ist, kann ein Fehler ausgeblendet werden : Notieren Sie alle SO-Beispiele, in denen Sie beim Schreiben von type * und type ** .
  • Die Idee, dass es Sie davon abhält, Sie zu bemerken, fehlgeschlagen ist, eine passende Header-Datei zu enthalten, vermisst die Gesamtstruktur für die Bäume . Es ist das gleiche wie zu sagen: “Mach dir keine Sorgen darüber, dass du es versäumt hast, den Compiler zu bitten, sich darüber zu beschweren, dass du keine Prototypen siehst – dieses nervtötende stdlib.h ist das ECHTE wichtige, an das du dich erinnern musst!”
  • Es erzwingt einen zusätzlichen kognitiven Gegencheck . Es stellt den (angeblichen) gewünschten Typ direkt neben die Arithmetik, die Sie für die rohe Größe dieser Variable tun. Ich wette, du könntest eine SO-Studie machen, die zeigt, dass malloc() Bugs viel schneller gefangen werden, wenn es einen Cast gibt. Wie bei Behauptungen verringern Anmerkungen, die Absicht aufzeigen, Fehler.
  • Sich selbst so zu wiederholen, dass die Maschine das überprüfen kann, ist oft eine gute Idee. In der Tat ist das eine Behauptung, und diese Verwendung von Besetzung ist eine Behauptung. Behauptungen sind immer noch die allgemeinste Technik, die wir haben, um den Code korrekt zu machen, da Turing vor so vielen Jahren auf diese Idee gekommen ist.

Wie bereits erwähnt, wird es nicht für C, sondern für C ++ benötigt. Wenn Sie meinen, dass Sie Ihren C-Code mit einem C ++ – Compiler kompilieren möchten, können Sie aus welchen Gründen auch immer ein Makro verwenden, wie zum Beispiel:

 #ifdef __cplusplus # define NEW(type, count) ((type *)calloc(count, sizeof(type))) #else # define NEW(type, count) (calloc(count, sizeof(type))) #endif 

So können Sie es immer noch sehr kompakt schreiben:

 int *sieve = NEW(int, 1); 

und es wird für C und C ++ kompilieren.

Aus der Wikipedia

Vorteile beim Gießen

  • Durch das Einbeziehen der Umwandlung kann ein C-Programm oder eine C-function möglicherweise als C ++ kompiliert werden.

  • Der Cast ermöglicht Versionen von malloc vor 1989, die ursprünglich ein char * zurückgegeben haben.

  • Casting kann dem Entwickler helfen, Inkonsistenzen in der Typisierung zu erkennen, sollte sich der Ziel-pointerstyp ändern, insbesondere wenn der pointers weit vom Aufruf malloc () entfernt deklariert wird (obwohl moderne Compiler und statische Analysatoren auf ein solches Verhalten warnen können, ohne dass der Cast erforderlich ist).

Nachteile beim Gießen

  • Gemäß dem ANSI C-Standard ist die Besetzung redundant.

  • Das Hinzufügen des Cast kann zu einem Maskenerrors führen und den Header stdlib.h enthalten , in dem der Prototyp für malloc gefunden wird. In Ermangelung eines Prototyps für malloc erfordert der Standard, dass der C-Compiler davon ausgeht, dass malloc einen int zurückgibt. Wenn keine Umwandlung vorliegt, wird eine Warnung ausgegeben, wenn diese Ganzzahl dem pointers zugewiesen wird. Bei der Besetzung wird diese Warnung jedoch nicht erzeugt und ein Fehler wird ausgeblendet. Bei bestimmten Architekturen und Datenmodellen (z. B. LP64 auf 64-Bit-Systemen, wobei long und pointers 64-Bit und int 32-Bit sind) kann dieser Fehler zu einem nicht definierten Verhalten führen, da das implizit deklarierte malloc eine 32- Bit zurückgibt. Bit-Wert, während die tatsächlich definierte function einen 64-Bit-Wert zurückgibt. Je nach Aufrufkonventionen und Speicherlayout kann dies zu einem Absturz des Stacks führen. Dieses Problem wird in modernen Compilern wahrscheinlich nicht unbemerkt bleiben, da sie einheitlich Warnungen ausgeben, dass eine nicht deklarierte function verwendet wurde, sodass weiterhin eine Warnung angezeigt wird. Beispielsweise zeigt das Standardverhalten von GCC eine Warnung an, die “inkompatible implizite Deklaration der integrierten function” liest, unabhängig davon, ob die Besetzung vorhanden ist oder nicht.

  • Wenn der Typ des pointerss bei seiner Deklaration geändert wird, müssen auch alle Zeilen geändert werden, in denen malloc aufgerufen und umgesetzt wird.

Obwohl malloc ohne Casting die bevorzugte Methode ist und die erfahrensten Programmierer es wählen , sollten Sie das verwenden, was Ihnen am besten gefällt.

Dh: Wenn Sie das C-Programm als C ++ kompilieren müssen (obwohl das eine separate Sprache ist), sollten Sie malloc mit Casting verwenden.

In C können Sie einen Void-pointers implizit in einen anderen Pointer-Typ konvertieren, sodass eine Umwandlung nicht erforderlich ist. Die Verwendung eines kann dem zufälligen Beobachter nahelegen, dass es einen Grund gibt, warum man benötigt wird, was irreführend sein kann.

Sie casting das Ergebnis von malloc nicht, weil dadurch Ihr Code sinnlos wird.

Der häufigste Grund, warum Menschen das Ergebnis von malloc ausspielen, ist, dass sie sich nicht sicher sind, wie die C-Sprache funktioniert. Das ist ein Warnzeichen: Wenn Sie nicht wissen, wie ein bestimmter Sprachmechanismus funktioniert, dann nehmen Sie keine Vermutung. Schaut es euch an oder fragt nach Stack Overflow.

Einige Kommentare:

  • Ein Void-pointers kann ohne explizite Umwandlung in einen anderen Pointer-Typ konvertiert werden (C11 6.3.2.3 und 6.5.16.1).

  • C ++ erlaubt jedoch keine implizite Umwandlung zwischen void* und einem anderen pointerstyp. In C ++ wäre die Besetzung also korrekt gewesen. Aber wenn Sie in C ++ programmieren, sollten Sie new und nicht malloc () verwenden. Und Sie sollten niemals C-Code mit einem C ++ – Compiler kompilieren.

    Wenn Sie sowohl C als auch C ++ mit demselben Quellcode unterstützen müssen, verwenden Sie Compiler-Schalter, um die Unterschiede zu markieren. Versuchen Sie nicht, beide Sprachstandards mit demselben Code zu sättigen, da sie nicht kompatibel sind.

  • Wenn ein C-Compiler eine function nicht finden kann, weil Sie vergessen haben, den Header einzuschließen, erhalten Sie einen Compiler / Linker-Fehler darüber. Wenn Sie also vergessen haben, das ist kein Problem, können Sie Ihr Programm nicht erstellen.

  • Bei älteren Compilern, die einer Version des Standards folgen, die älter als 25 Jahre ist, würde das Vergessen von zu gefährlichem Verhalten führen. Weil in diesem alten Standard functionen ohne einen sichtbaren Prototyp den Rückgabetyp implizit in int umwandelten. Wenn das Ergebnis von malloc explizit übertragen würde, würde dieser Fehler dann ausgeblendet.

    Aber das ist wirklich kein Thema. Sie benutzen keinen 25 Jahre alten Computer, warum sollten Sie einen 25 Jahre alten Compiler verwenden?

In C erhalten Sie eine implizite Umwandlung von void* in einen anderen (Daten) -pointers.

Es ist jetzt nicht notwendig, den von malloc() Wert zu übergeben, aber ich möchte einen Punkt hinzufügen, auf den niemand hingewiesen zu haben scheint:

In den alten Tagen, dh bevor ANSI C den void * als generischen Typ von pointersn bereitstellt, ist char * der Typ für eine solche Verwendung. In diesem Fall kann die Besetzung die Compiler-Warnungen herunterfahren.

Referenz: C FAQ

Die Ergebnisse von malloc müssen nicht zwingend umgesetzt werden, da void* wird und void* auf einen beliebigen Datentyp verweisen kann.

Ich füge meine Erfahrung hinzu und studiere Computer-Engineering. Ich sehe, dass die zwei oder drei Professoren, die ich in C geschrieben habe, immer malloc gecastet haben, aber der, den ich fragte (mit einem immensen Lebenslauf und Verständnis für C), sagte mir, dass es absolut unnötig ist war früher sehr spezifisch und um die Schüler in die Mentalität zu bringen, absolut spezifisch zu sein. Im Wesentlichen wird Casting nichts daran ändern, wie es funktioniert, es tut genau das, was es sagt, reserviert Speicher, und das Casting beeinflusst es nicht, du bekommst das selbe Gedächtnis und sogar wenn du es irrtümlich auf etwas anderes transformierst (und irgendwie dem Compiler entgeht) Fehler) C wird auf die gleiche Weise zugreifen.

Edit: Casting hat einen bestimmten Punkt. Wenn Sie die Array-Notation verwenden, muss der generierte Code wissen, wie viele Speicherplätze er vorrücken muss, um den Anfang des nächsten Elements zu erreichen. Dies wird durch Casting erreicht. Auf diese Weise wissen Sie, dass Sie für ein Double 8 Bytes voraus gehen, während Sie für ein int 4 gehen und so weiter. Daher hat es keine Wirkung, wenn Sie die pointers-Notation verwenden, in der Array-Notation wird es notwendig.

Der zurückgegebene Typ ist void * und kann in den gewünschten Datenzeiger umgewandelt werden, um dereferenziert zu werden.

Ein Void-pointers ist ein generischer pointers, und C unterstützt die implizite Konvertierung von einem void-pointers-Typ in andere Typen, so dass es nicht notwendig ist, diesen explizit zu typisieren.

Wenn Sie jedoch möchten, dass derselbe Code auf einer C ++ – Plattform, die keine implizite Konvertierung unterstützt, perfekt kompatibel ist, müssen Sie die Typumwandlung durchführen, daher kommt es auf die Benutzerfreundlichkeit an.

Hinzufügen zu allen Informationen hier; Dies ist, was in der GNU C-Bibliothek Referenzhandbuch heißt:

Sie können das Ergebnis von malloc in einer beliebigen pointersvariablen ohne eine Umwandlung speichern, da ISO C den Typ void * bei Bedarf automatisch in einen anderen Typ von pointers konvertiert. Die Besetzung ist jedoch in anderen Kontexten als Zuweisungsoperatoren erforderlich, oder wenn Sie möchten, dass Ihr Code in einem traditionellen C ausgeführt wird.

Und tatsächlich sagt der ISO C11 Standard (p347) so:

Der pointers, der zurückgegeben wird, wenn die Zuweisung erfolgreich ist, wird passend ausgerichtet, so dass er einem pointers auf einen beliebigen Objekttyp mit einer fundamentalen Ausrichtungsanforderung zugewiesen werden kann und dann verwendet wird, um auf ein solches Objekt oder ein Array von solchen Objekten in dem zugewiesenen Raum zuzugreifen Speicherplatz wird explizit freigegeben

Es hängt von der Programmiersprache und dem Compiler ab. Wenn Sie malloc in C verwenden, müssen Sie es nicht eingeben, da es automatisch den Cast eingibt. Wenn Sie jedoch C ++ verwenden, sollten Sie Cast malloc da malloc einen void* -Typ malloc .

In der C-Sprache kann jedem pointers ein void-pointers zugewiesen werden, weshalb Sie keinen Typ-Cast verwenden sollten. Wenn Sie eine sichere Zuordnung wünschen, kann ich die folgenden Makrofunktionen empfehlen, die ich immer in meinen C-Projekten verwende:

 #include  #define NEW_ARRAY(ptr, n) (ptr) = malloc((n) * sizeof *(ptr)) #define NEW(ptr) NEW_ARRAY((ptr), 1) 

Mit diesen können Sie einfach sagen

 NEW_ARRAY(sieve, length); 

Für nicht dynamische Arrays ist das dritte Must-Have-functionsmakro

 #define LEN(arr) (sizeof (arr) / sizeof (arr)[0]) 

Das macht Array-Schleifen sicherer und bequemer:

 int i, a[100]; for (i = 0; i < LEN(a); i++) { ... } 

Casting ist nur für C ++ nicht C. Wenn Sie einen C ++ – Compiler verwenden, sollten Sie ihn besser in C-Compiler umwandeln.

Leute, die an GCC und Clang gewöhnt sind, sind verwöhnt. Es ist nicht so gut da draußen.

Ich war über die Jahre ziemlich erschrocken von den erstaunlich alten Compilern, die ich benutzen musste. Unternehmen und Manager wenden oft einen sehr konservativen Ansatz zum Ändern von Compilern an und testen nicht einmal , ob ein neuer Compiler (mit besserer Einhaltung von Standards und Code-Optimierung) in seinem System funktioniert. Die praktische Realität für Entwickler ist, dass Sie beim Codieren Ihre Grundlagen abdecken müssen und Casting von mallocs ist eine gute Angewohnheit, wenn Sie nicht kontrollieren können, welcher Compiler auf Ihren Code angewendet wird.

Ich würde auch vorschlagen, dass viele Organisationen einen eigenen Kodierungsstandard anwenden und dass dies die Methode sein sollte, der die Leute folgen, wenn sie definiert ist. In Ermangelung einer ausdrücklichen Anleitung tendiere ich dazu, am ehesten überall zu kompilieren, anstatt die Einhaltung eines Standards zu sklavieren.

Das Argument, dass es unter den gegenwärtigen Standards nicht notwendig ist, ist durchaus berechtigt. Aber dieses Argument lässt die praktischen Aspekte der realen Welt aus. Wir kodieren nicht in einer Welt, die ausschließlich vom Standard des Tages beherrscht wird, sondern von den praktischen Dingen, die ich “Realitätsfeld des lokalen Managements” nenne. Und das ist gebogen und verdreht mehr als Raum Zeit jemals war. 🙂

YMMV.

Ich tendiere dazu, Malloc als eine Verteidigungsoperation zu betrachten. Nicht schön, nicht perfekt, aber im Allgemeinen sicher. (Ehrlich gesagt, wenn Sie stdlib.h nicht mit einbezogen haben, haben Sie viel mehr Probleme als das Casting von malloc!).

Ich setze die Besetzung einfach ein, um Missbilligung des hässlichen Lochs im Typsystem zu zeigen, das Code wie den folgenden Ausschnitt erlaubt, ohne Diagnose zu kompilieren, obwohl keine Umwandlungen verwendet werden, um die schlechte Umwandlung herbeizuführen:

 double d; void *p = &d; int *q = p; 

Ich wünschte, das existierte nicht (und es ist nicht in C ++) und so habe ich gegossen. Es repräsentiert meinen Geschmack und meine Programmpolitik. Ich werfe nicht nur einen pointers auf, sondern gebe effektiv einen Stimmzettel ab und vertreibe Dämonen der Dummheit . Wenn ich die Dummheit nicht wirklich austreiben kann , dann möchte ich wenigstens mit einer Protestgeste den Wunsch zum Ausdruck bringen.

In der Tat ist es eine gute Übung, malloc (und friends) mit functionen zu umhüllen, die unsigned char * , und im Prinzip niemals void * in Ihrem Code zu verwenden. Wenn Sie ein generisches pointer-an-any-Objekt benötigen, verwenden Sie char * oder unsigned char * und lassen Sie Umwandlungen in beide Richtungen zu. The one relaxation that can be indulged, perhaps, is using functions like memset and memcpy without casts.

On the topic of casting and C++ compatibility, if you write your code so that it compiles as both C and C++ (in which case you have to cast the return value of malloc when assigning it to something other than void * ), you can do a very helpful thing for yourself: you can use macros for casting which translate to C++ style casts when compiling as C++, but reduce to a C cast when compiling as C:

 /* In a header somewhere */ #ifdef __cplusplus #define strip_qual(TYPE, EXPR) (const_cast(EXPR)) #define convert(TYPE, EXPR) (static_cast(EXPR)) #define coerce(TYPE, EXPR) (reinterpret_cast(EXPR)) #else #define strip_qual(TYPE, EXPR) ((TYPE) (EXPR)) #define convert(TYPE, EXPR) ((TYPE) (EXPR)) #define coerce(TYPE, EXPR) ((TYPE) (EXPR)) #endif 

If you adhere to these macros, then a simple grep search of your code base for these identifiers will show you where all your casts are, so you can review whether any of them are incorrect.

Then, going forward, if you regularly compile the code with C++, it will enforce the use of an appropriate cast. For instance, if you use strip_qual just to remove a const or volatile , but the program changes in such a way that a type conversion is now involved, you will get a diagnostic, and you will have to use a combination of casts to get the desired conversion.

To help you adhere to these macros, the the GNU C++ (not C!) compiler has a beautiful feature: an optional diagnostic which is produced for all occurrences of C style casts.

     -Wold-style-cast (C++ and Objective-C++ only)
         Warn if an old-style (C-style) cast to a non-void type is used
         within a C++ program. The new-style casts (dynamic_cast,
         static_cast, reinterpret_cast, and const_cast) are less vulnerable
         to unintended effects and much easier to search for.

If your C code compiles as C++, you can use this -Wold-style-cast option to find out all occurrences of the (type) casting syntax that may creep into the code, and follow up on these diagnostics by replacing it with an appropriate choice from among the above macros (or a combination, if necessary).

This treatment of conversions is the single largest standalone technical justification for working in a “Clean C”: the combined C and C++ dialect, which in turn technically justifies casting the return value of malloc .

The concept behind void pointer is that it can be casted to any data type that is why malloc returns void. Also you must be aware of automatic typecasting. So it is not mandatory to cast the pointer though you must do it. It helps in keeping the code clean and helps debugging

The best thing to do when programming in C whenever it is possible:

  1. Make your program compile through a C compiler with all warnings turned on -Wall and fix all errors and warnings
  2. Make sure there are no variables declared as auto
  3. Then compile it using a C++ compiler with -Wall and -std=c++11 . Fix all errors and warnings.
  4. Now compile using the C compiler again. Your program should now compile without any warning and contain fewer bugs.

This procedure lets you take advantage of C++ strict type checking, thus reducing the number of bugs. In particular, this procedure forces you to include stdlib.h or you will get

malloc was not declared within this scope

and also forces you to cast the result of malloc or you will get

invalid conversion from void* to T*

or what ever your target type is.

The only benefits from writing in C instead of C++ I can find are

  1. C has a well specified ABI
  2. C++ may generate more code [exceptions, RTTI, templates, runtime polymorphism]

Notice that the second cons should in the ideal case disappear when using the subset common to C together with the static polymorphic feature.

For those that finds C++ strict rules inconvenient, we can use the C++11 feature with inferred type

 auto memblock=static_cast(malloc(n*sizeof(T))); //Mult may overflow... 

No, you don’t cast the result of malloc() .

In general, you don’t cast to or from void * .

A typical reason given for not doing so is that failure to #include could go unnoticed. This isn’t an issue anymore for a long time now as C99 made implicit function declarations illegal, so if your compiler conforms to at least C99, you will get a diagnostic message.

But there’s a much stronger reason not to introduce unnecessary pointer casts:

In C, a pointer cast is almost always an error . This is because of the following rule ( §6.5 p7 in N1570, the latest draft for C11):

An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
— a type compatible with the effective type of the object,
— a qualified version of a type compatible with the effective type of the object,
— a type that is the signed or unsigned type corresponding to the effective type of the object,
— a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
— an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
— a character type.

This is also known as the strict aliasing rule . So the following code is undefined behavior :

 long x = 5; double *p = (double *)&x; double y = *p; 

And, sometimes surprisingly, the following is as well:

 struct foo { int x; }; struct bar { int x; int y; }; struct bar b = { 1, 2}; struct foo *p = (struct foo *)&b; int z = p->x; 

Sometimes, you do need to cast pointers, but given the strict aliasing rule , you have to be very careful with it. So, any occurrence of a pointer cast in your code is a place you have to double-check for its validity . Therefore, you never write an unnecessary pointer cast.

tl;dr

In a nutshell: Because in C, any occurrence of a pointer cast should raise a red flag for code requiring special attention, you should never write unnecessary pointer casts.


Randnotizen:

  • There are cases where you actually need a cast to void * , eg if you want to print a pointer:

     int x = 5; printf("%p\n", (void *)&x); 

    The cast is necessary here, because printf() is a variadic function, so implicit conversions don’t work.

  • In C++, the situation is different. Casting pointer types is somewhat common (and correct) when dealing with objects of derived classes. Therefore, it makes sense that in C++, the conversion to and from void * is not implicit. C++ has a whole set of different flavors of casting.

I prefer to do the cast, but not manually. My favorite is using g_new and g_new0 macros from glib. If glib is not used, I would add similar macros. Those macros reduce code duplication without compromising type safety. If you get the type wrong, you would get an implicit cast between non-void pointers, which would cause a warning (error in C++). If you forget to include the header that defines g_new and g_new0 , you would get an error. g_new and g_new0 both take the same arguments, unlike malloc that takes fewer arguments than calloc . Just add 0 to get zero-initialized memory. The code can be compiled with a C++ compiler without changes.

A void pointer is a generic pointer and C supports implicit conversion from a void pointer type to other types, so there is no need of explicitly typecasting it.

However, if you want the same code work perfectly compatible on a C++ platform, which does not support implicit conversion, you need to do the typecasting, so it all depends on usability.

  1. As other stated, it is not needed for C, but for C++.

  2. Including the cast may allow a C program or function to compile as C++.

  3. In C it is unnecessary, as void * is automatically and safely promoted to any other pointer type.

  4. But if you cast then, it can hide an error if you forgot to include stdlib.h . This can cause crashes (or, worse, not cause a crash until way later in some totally different part of the code).

    Because stdlib.h contains the prototype for malloc is found. In the absence of a prototype for malloc, the standard requires that the C compiler assumes malloc returns an int. If there is no cast, a warning is issued when this integer is assigned to the pointer; however, with the cast, this warning is not produced, hiding a bug.

The casting of malloc is unnecessary in C but mandatory in C++.

  • Casting is unnecessary in C because of void * is automatically and safely promoted to any other pointer type in this case.
  • It can hide an error if you forgot to include . This can cause crashes.
  • If pointers and integers are differently sized, then you’re hiding a warning by casting and might lose bits of your returned address.

Please do yourself a favor and more importantly a favor for the next person who will maintain your code, and provide as much information as possible about the data type of a program’s variables.

Thus, cast the returned pointer from malloc . In the following code the compiler can be assured that sieve is in fact being assigned a point to an integer(s).

  int *sieve = (int *) malloc(sizeof(int) * length); 

This reduces the chance for a human error when/if the data type for sieve is changed.

I would be interested in knowing if there are any “pure” C compilers that would flag this statement as being in error. If so, let me know, so that I can avoid them as their lack of type checking will increase the overall expense of maintaining software.