1

About something I read here(Type Safety paragraph): https://en.wikipedia.org/wiki/C_dynamic_memory_allocation

It says that in this code:

int *ptr, *ptr2;
ptr = malloc(10 * sizeof(*ptr)); /* without a cast */
ptr2 = (int *)malloc(10 * sizeof(*ptr)); /* with a cast */

an advantage of casting is "The cast allows for pre-1989 versions of malloc that originally returned a char *"

I don't understand, why is it important to cast it in order to be compatible with pre-1989 versions. In those versions, malloc returned char* and not void*, so malloc(10 * sizeof(*ptr)); will return a char pointer that contains the address of the allocated data, and then in ptr = malloc(10 * sizeof(*ptr)); ptr will point to the allocated data. the int * ptr will just point to the address pointed by the returned char *. So, the code without the casting should work on previous versions of C.

user3787309
  • 109
  • 1
  • 1
  • 4
  • 1
    Well, the code would _work_ with pre 89 C compiler, but it would'nt compile. – Jabberwocky Apr 05 '23 at 08:07
  • 2
    Related: https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc Also, please note the lurking "bug" in the second allocation: it uses `sizeof(*ptr)` instead of `sizeof(*ptr2)` and while they are the same, now, the code may change. – Bob__ Apr 05 '23 at 08:13
  • btw.. `sizeof` is not a function. It is an operator, line unary `-`. There is no need doing `sizeof(x)` while one can do `sizeof x`. The same way as for`-(1)`. – tstanisl Apr 05 '23 at 08:37
  • When you are worrying about the pre-89 behavior of C before it was standardized -- you may be putting effort into the wrong place. History has value, but for current code, the `void*` returned since that time needs no cast. What I would find interesting is whether there was any difference in the type returned by the varying flavors of C pre-89? (more dusty information relegated to the depths of my mind...) – David C. Rankin Apr 05 '23 at 09:12

2 Answers2

2

Because only a void* can be assigned to any other pointer type:

For example:

void *mymalloc(int size);   // similar to modern malloc declaration

int main(void) {
    int *i;
    i = mymalloc(10); // will compile: you can assign a void* to any pointer
}
char *mymalloc(int size); // similar to pre C89 malloc declaration

int main(void) {
    int *i;
    i = mymalloc(10); // won't compile: you can't assign a char* to an int*
    i = (char*)mymalloc(10); // will compile
}
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • Thank you. About what you wrote, In my compiler I can assign any pointer to any other pointer, it produces a warning but compiles. Is it something that works only in recent compilers ? – user3787309 Apr 05 '23 at 08:30
  • 1
    If neither of the pointer types is `void*` you'll get the warning without a cast. Also see [What is the strict aliasing rule?](https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule) – Weather Vane Apr 05 '23 at 09:06
0

I don't understand, why is it important to cast it in order to be compatible with pre-1989 versions.

It is not the slightest important, to the point where this isn't even a valid argument. Even the argument of "casting may hide bugs when forgetting to include stdlib." is questionable, since that's only a problem in old C90, which was withdrawn 24 years ago.


So, the code without the casting should work on previous versions of C.

No, because not even pre-standard C versions allowed (afaik) implicit pointer conversions. In standard C we have this constraint (C17 6.5.4)

Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.

Where "the constraints of 6.5.16.1" lists the valid forms of assignment, you can find the complete list below "Pointer from integer/integer from pointer without a cast" issues. There is one bullet covering the special case of assigning to/from void* and that is the only implicit pointer conversion which was ever allowed in C. And void* were introduced around the point of standardization in the late 1980s.

Lundin
  • 195,001
  • 40
  • 254
  • 396