Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

84%
+9 −0
Q&A How to properly use malloc?

Should we cast the result of malloc? The cast to the intended type is not necessary in C, since during assignment, the void* returned by malloc can be implicitly converted to any other object poin...

posted 3y ago by Lundin‭  ·  edited 1y ago by Lundin‭

Answer
#2: Post edited by user avatar Lundin‭ · 2023-08-10T10:59:15Z (over 1 year ago)
  • **Should we cast the result of malloc?**
  • The cast to the intended type is not necessary in C, since during assignment, the `void*` returned by `malloc` can be implicitly converted to any other object pointer and vice versa (as per C17 6.5.16.1). So the cast does add clutter. _However_, there's nothing wrong with being explicit by types either, so it is mostly a matter of coding style.
  • There are some historical and compatibility reasons why you would/shouldn't cast:
  • - C++ doesn't allow implicit conversions with void pointers so the cast is necessary if C++ compatibility is desired. (However, using `malloc` in C++ is very questionable and dangerous, but that's another story.)
  • - The old C90 standard supported dangerous implicit int default function declarations, so if you forgot to `#include <stdlib.h>` then added a cast to the `malloc` result, you would hide the bug that the missing include introduced.
  • **How should we write the size parameter to malloc?**
  • There's several possible options here:
  • 1. `malloc( n * sizeof(int) )`
  • 2. `malloc( sizeof(int[n]) )`
  • 3. `malloc( n * sizeof *p )`
  • 4. `calloc( n, sizeof(int) )`
  • 5. `calloc( n, sizeof *p )`
  • - `malloc( n * sizeof(int) )` has the advantage of being clear and explicit, this would be the most "old scool" way of using `malloc` and probably the most common method taught in C books.
  • The argument against this style is that in case we change the type of `p`, then the `malloc` call turns incorrect. I always thought that this was a rather weak argument - because: yes if you only change part of a code without considering all of it, it will break. That goes for all C code.
  • - `malloc( sizeof(int[n]) )` is very similar to the above one, except it is slightly more readable. It uses a VLA declaration though, so it's not 100% portable to old or exotic C implementations.
  • - `malloc( n * sizeof *p )` uses a trick, namely that the `sizeof` operand isn't evaluated for side-effects here, so we can actually de-reference a pointer to get the size of the pointed-at type, without the code actually executing that de-referencing (which would have been wildly undefined behavior).
  • The argument in favour of this style is the opposite of the argument against the above ones - in case `p` changes type then the `malloc` expression is still valid. That's nice. Arguments against this style will follow further below.
  • - The `calloc` versions are 100% equivalent to their `malloc` counterparts, except it will also zero-out all memory. Meaning `calloc` is slower but it provides extra functionality.
  • ---
  • **Why `sizeof *p` isn't some universally great style**
  • The argument for using the `*p` style doesn't scale well when we start dealing with more complex situations like pointer-to-pointers or 2D arrays. Consider this:
  • ```c
  • void failloc (int n, int p[5][5])
  • {
  • p = malloc(n * sizeof *p);
  • printf("Yay we allocated %zu bytes\n", n * sizeof *p);
  • }
  • ```
  • When calling this code as `failloc(1, arr)` then we expect `1*5*5*sizeof(int)` bytes = 100 bytes on 32 bit computer. However, it only allocates `1 * sizeof(int(*)[5])`. That is, 20 bytes, which is of course wrong.
  • One may then argue and say hey, you picked the wrong type, it should have been `int (*p)[5][5]` and the code will work. Yes indeed, _if I change the type of `p` it will start working_. Now, what was the initial argument for using this style again?
  • In case an `int**` was passed to a similar function, then again the style doesn't scale well, consider this (bad!) code:
  • ```c
  • int** failloc (int x, int y,)
  • {
  • int** p = malloc(x * sizeof *p);
  • for(int i=0; i<y; i++)
  • p[i] = malloc(y * sizeof **p);
  • return p;
  • }
  • ```
  • We have to do `**p` suddenly which is inconsistent. Now what if I change the type of `p` to `int*`? Hey, you can't go change the type of `p` again, stop doing that!
  • Yet another scenario: flexible array members.
  • ```c
  • typedef struct
  • {
  • int foo;
  • int bar[];
  • } flexy;
  • flexy* p = malloc(sizeof *p + n * sizeof /* what? */ );
  • ```
  • We can't write `sizeof *bar`, there's no such identifier. We have to write `sizeof *p->bar`. This simply isn't readable.
  • The only sensible way out is to combine the `*p` style with one of the other two. Personally I'd probably have written that line as
  • malloc( sizeof *p + sizeof(int[n]) );
  • Or for those who insist on using the same style consistently:
  • malloc(sizeof(flexy) + n * sizeof(int) );
  • ---
  • So overall I don't think the `sizeof *p` trick is nearly as smart as people like to claim, it's nice in some situations, it doesn't work in other situations.
  • Overall the programmer must actually know what they are doing - no way around it. If you change the type of some variable, then you better review every single line in the code base using that variable - simple as that.
  • I don't think any of these styles come with any significant benefits or strong arguments for using one over the other - it is all very subjective. There is no obvious right or wrong style here.
  • **Should we cast the result of malloc?**
  • The cast to the intended type is not necessary in C, since during assignment, the `void*` returned by `malloc` can be implicitly converted to any other object pointer and vice versa (as per C17 6.5.16.1). So the cast does add clutter. _However_, there's nothing wrong with being explicit by types either, so it is mostly a matter of coding style.
  • There are some historical and compatibility reasons why you would/shouldn't cast:
  • - C++ doesn't allow implicit conversions with void pointers so the cast is necessary if C++ compatibility is desired. (However, using `malloc` in C++ is very questionable and dangerous, but that's another story.)
  • - The old C90 standard supported dangerous implicit int default function declarations, so if you forgot to `#include <stdlib.h>` then added a cast to the `malloc` result, you would hide the bug that the missing include introduced.
  • **How should we write the size parameter to malloc?**
  • There's several possible options here:
  • 1. `malloc( n * sizeof(int) )`
  • 2. `malloc( sizeof(int[n]) )`
  • 3. `malloc( n * sizeof *p )`
  • 4. `calloc( n, sizeof(int) )`
  • 5. `calloc( n, sizeof *p )`
  • - `malloc( n * sizeof(int) )` has the advantage of being clear and explicit, this would be the most "old scool" way of using `malloc` and probably the most common method taught in C books.
  • The argument against this style is that in case we change the type of `p`, then the `malloc` call turns incorrect. I always thought that this was a rather weak argument - because: yes if you only change part of a code without considering all of it, it will break. That goes for all C code.
  • - `malloc( sizeof(int[n]) )` is very similar to the above one, except it is slightly more readable. It uses a VLA declaration though, so it's not 100% portable to old or exotic C implementations.
  • - `malloc( n * sizeof *p )` uses a trick, namely that the `sizeof` operand isn't evaluated for side-effects here, so we can actually de-reference a pointer to get the size of the pointed-at type, without the code actually executing that de-referencing (which would have been wildly undefined behavior).
  • The argument in favour of this style is the opposite of the argument against the above ones - in case `p` changes type then the `malloc` expression is still valid. That's nice. Arguments against this style will follow further below.
  • - The `calloc` versions are 100% equivalent to their `malloc` counterparts, except it will also zero-out all memory. Meaning `calloc` is slower but it provides extra functionality.
  • ---
  • **Why `sizeof *p` isn't some universally great style**
  • The argument for using the `*p` style doesn't scale well when we start dealing with more complex situations like pointer-to-pointers or 2D arrays. Consider this:
  • ```c
  • void failloc (int n, int p[5][5])
  • {
  • p = malloc(n * sizeof *p);
  • printf("Yay we allocated %zu bytes\n", n * sizeof *p);
  • }
  • ```
  • When calling this code as `failloc(1, arr)` then we expect `1*5*5*sizeof(int)` bytes = 100 bytes on 32 bit computer. However, it only allocates `1 * sizeof(int[5])`. That is, 20 bytes, which is of course wrong.
  • One may then argue and say hey, you picked the wrong type, it should have been `int (*p)[5][5]` and the code will work. Yes indeed, _if I change the type of `p` it will start working_. Now, what was the initial argument for using this style again?
  • In case an `int**` was passed to a similar function, then again the style doesn't scale well, consider this (bad!) code:
  • ```c
  • int** failloc (int x, int y,)
  • {
  • int** p = malloc(x * sizeof *p);
  • for(int i=0; i<y; i++)
  • p[i] = malloc(y * sizeof **p);
  • return p;
  • }
  • ```
  • We have to do `**p` suddenly which is inconsistent. Now what if I change the type of `p` to `int*`? Hey, you can't go change the type of `p` again, stop doing that!
  • Yet another scenario: flexible array members.
  • ```c
  • typedef struct
  • {
  • int foo;
  • int bar[];
  • } flexy;
  • flexy* p = malloc(sizeof *p + n * sizeof /* what? */ );
  • ```
  • We can't write `sizeof *bar`, there's no such identifier. We have to write `sizeof *p->bar`. This simply isn't readable.
  • The only sensible way out is to combine the `*p` style with one of the other two. Personally I'd probably have written that line as
  • malloc( sizeof *p + sizeof(int[n]) );
  • Or for those who insist on using the same style consistently:
  • malloc(sizeof(flexy) + n * sizeof(int) );
  • ---
  • So overall I don't think the `sizeof *p` trick is nearly as smart as people like to claim, it's nice in some situations, it doesn't work in other situations.
  • Overall the programmer must actually know what they are doing - no way around it. If you change the type of some variable, then you better review every single line in the code base using that variable - simple as that.
  • I don't think any of these styles come with any significant benefits or strong arguments for using one over the other - it is all very subjective. There is no obvious right or wrong style here.
#1: Initial revision by user avatar Lundin‭ · 2022-02-10T11:26:53Z (almost 3 years ago)
**Should we cast the result of malloc?**

The cast to the intended type is not necessary in C, since during assignment, the `void*` returned by `malloc` can be implicitly converted to any other object pointer and vice versa (as per C17 6.5.16.1). So the cast does add clutter. _However_, there's nothing wrong with being explicit by types either, so it is mostly a matter of coding style.

There are some historical and compatibility reasons why you would/shouldn't cast:
- C++ doesn't allow implicit conversions with void pointers so the cast is necessary if C++ compatibility is desired. (However, using `malloc` in C++ is very questionable and dangerous, but that's another story.)
- The old C90 standard supported dangerous implicit int default function declarations, so if you forgot to `#include <stdlib.h>` then added a cast to the `malloc` result, you would hide the bug that the missing include introduced.

**How should we write the size parameter to malloc?**

There's several possible options here:

1. `malloc( n * sizeof(int) )`
2. `malloc( sizeof(int[n]) )`
3. `malloc( n * sizeof *p )`
4. `calloc( n, sizeof(int) )`
5. `calloc( n, sizeof *p )`

- `malloc( n * sizeof(int) )` has the advantage of being clear and explicit, this would be the most "old scool" way of using `malloc` and probably the most common method taught in C books.

  The argument against this style is that in case we change the type of `p`, then the `malloc` call turns incorrect. I always thought that this was a rather weak argument - because: yes if you only change part of a code without considering all of it, it will break. That goes for all C code.

- `malloc( sizeof(int[n]) )` is very similar to the above one, except it is slightly more readable. It uses a VLA declaration though, so it's not 100% portable to old or exotic C implementations.

- `malloc( n * sizeof *p )` uses a trick, namely that the `sizeof` operand isn't evaluated for side-effects here, so we can actually de-reference a pointer to get the size of the pointed-at type, without the code actually executing that de-referencing (which would have been wildly undefined behavior).

  The argument in favour of this style is the opposite of the argument against the above ones - in case `p` changes type then the `malloc` expression is still valid. That's nice. Arguments against this style will follow further below.

- The `calloc` versions are 100% equivalent to their `malloc` counterparts, except it will also zero-out all memory. Meaning `calloc` is slower but it provides extra functionality.

---

**Why `sizeof *p` isn't some universally great style**

The argument for using the `*p` style doesn't scale well when we start dealing with more complex situations like pointer-to-pointers or 2D arrays. Consider this:

```c
void failloc (int n, int p[5][5])
{
  p = malloc(n * sizeof *p);
  printf("Yay we allocated %zu bytes\n", n * sizeof *p);
}
```

When calling this code as `failloc(1, arr)` then we expect `1*5*5*sizeof(int)` bytes = 100 bytes on 32 bit computer. However, it only allocates `1 * sizeof(int(*)[5])`. That is, 20 bytes, which is of course wrong.

One may then argue and say hey, you picked the wrong type, it should have been `int (*p)[5][5]` and the code will work. Yes indeed, _if I change the type of `p` it will start working_. Now, what was the initial argument for using this style again?

In case an `int**` was passed to a similar function, then again the style doesn't scale well, consider this (bad!) code:

```c
int** failloc (int x, int y,)
{
  int** p = malloc(x * sizeof *p);
  for(int i=0; i<y; i++)
    p[i] = malloc(y * sizeof **p);
  return p;
}
```

We have to do `**p` suddenly which is inconsistent. Now what if I change the type of `p` to `int*`? Hey, you can't go change the type of `p` again, stop doing that! 

Yet another scenario: flexible array members. 

```c
typedef struct
{
  int foo;
  int bar[];
} flexy;

flexy* p = malloc(sizeof *p + n * sizeof /* what? */ );
```

We can't write `sizeof *bar`, there's no such identifier. We have to write `sizeof *p->bar`. This simply isn't readable.

The only sensible way out is to combine the `*p` style with one of the other two. Personally I'd probably have written that line as

    malloc( sizeof *p + sizeof(int[n]) );


Or for those who insist on using the same style consistently:

    malloc(sizeof(flexy) + n * sizeof(int) );

---

  So overall I don't think the `sizeof *p` trick is nearly as smart as people like to claim, it's nice in some situations, it doesn't work in other situations. 

Overall the programmer must actually know what they are doing - no way around it. If you change the type of some variable, then you better review every single line in the code base using that variable - simple as that. 

I don't think any of these styles come with any significant benefits or strong arguments for using one over the other - it is all very subjective. There is no obvious right or wrong style here.