-1

Correct way:

int *x = (int *) malloc(sizeof(int) * 5);
void *x = (int *) malloc(sizeof(int) * 5);

Incorrect way:

int *x (int *) = malloc(sizeof(int) * 5);

What is the reason for this syntax? Because the pointer is the one that iterates, shouldn't the casting be to it (so it knows how many bytes to iterate)?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 1
    `malloc` returns a `void *`. You are telling the compiler to treat that `void *` as an `int *` so it goes with the `malloc`. – 001 Oct 18 '22 at 18:38
  • 2
    Side note: [Do I cast the result of malloc?](https://stackoverflow.com/q/605845) – 001 Oct 18 '22 at 18:38
  • 1
    You cast the return value of malloc, and then assign the result of the cast to x. The assigned value is the right side of =, ergo, the cast belongs there. – Seva Alekseyev Oct 18 '22 at 18:39
  • 1
    _so it knows how many bytes to iterate_ Not sure what that means. – 001 Oct 18 '22 at 18:39
  • 1
    C *doesn't* require casting of the right side. Anyway the second example is contradictory: `malloc` returns `void*` so why would you cast it to `int*` to assign it to `void *x`? – Weather Vane Oct 18 '22 at 18:39
  • @JohnnyMopp "so it knows how many bytes to iterate" - sorry, I mean to access say an integer, the pointer would need to know the data type hence casting, thus to get the next int in memory it would go up 4 bytes as apposed to 1 for a char – Mark Thomas Oct 18 '22 at 18:42
  • 1
    Please read Johnny's link. There is lot of information there. – Weather Vane Oct 18 '22 at 18:43
  • Ah ok, thank you all. That makes more sense! Of course if anyone has additional info please comment too. – Mark Thomas Oct 18 '22 at 18:44
  • 1
    You've already told the compiler how many bytes because you declare it as `int *x`, so the cast is not relevant to that. Note, you can't iterate a `void *`. [Can I do arithmetic on void \* pointers in C?](https://stackoverflow.com/a/4019692) – 001 Oct 18 '22 at 18:45
  • @JohnnyMopp Thank you very much for you in depth answers - you've helped me and a classmate !! – Mark Thomas Oct 18 '22 at 18:48
  • It's quite simple: A cast is a conversion of a value from one type to another. You want to convert what's on the RHS to the type of variable to which you are assigning on the LHS, so you cast the RHS. (Note that no explicit cast when going from a `void*` to another pointer type and vice-versa, so no explicit cast is needed here, and it should be avoided.) – ikegami Oct 18 '22 at 20:02
  • 1
    The most correct way is `int *x = malloc(5 * sizeof *x);` – tstanisl Oct 18 '22 at 20:58

1 Answers1

1

First a quibble: The = characters in your code indicate initializations, not assignment. The semantics are similar, at least in this case.

A cast on the left side of an assignment would not make sense.

A cast operator takes an operand of some type and yields a value of some (other) type.

It might help to think of a cast operator as something similar to a function call. Let's say you have a function named convert_value. It makes sense to write:

some_type target_object = convert_value(foo);

or

some_type target_object;
target_object = convert_value(foo);

There's no reasonable way to express that with the function call on the left side of the assignment. The left side denotes an object, not a value; a cast yields a value.

(You can have a cast as part of the name on the left side of an expression, but not at the top level.)

And in this particular case, no cast is required. Rather than

int *x = (int *) malloc(sizeof(int) * 5);

it's best to write:

int *x = malloc(5 * sizeof *x);

An assignment or initialization will implicitly convert a void* value to the target pointer type, and the sizeof *x style means you don't have to repeat the type name (which can be error-prone, especially if the code is modified later).

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631