Search code examples
cpointerscasting

Why does casting with a pointer require casting on the right side of the assignment (=)?


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)?


Solution

  • 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).