0

In C, a void pointer is declared, usually, like this:

int a = 10; 
char b = 'x'; 
  
void *p = &a;  // void pointer holds address of int 'a' 
p = &b; // void pointer holds address of char 'b' 

However, the syntax of malloc in C is like this:

ptr = (cast-type*) malloc(byte-size)

What I can't understand is why the "*" symbol in the "cast-type" section of the code above is on the right. I would assume the correct way of writing the same line of code would be like this:

ptr = (*cast-type) malloc(byte-size)

That's because when declaring a pointer the "*" is on the left, not on the right.

What's the problem with my reasoning?

Daniel Zardo
  • 127
  • 6
  • 3
    Aside: please see [Do I cast the result of malloc?](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Weather Vane Oct 10 '20 at 17:41
  • 1
    Because that is the syntax: look at the way you defined `void *p`. The `*` is on the right of the *type* and you could have defined `void* p` although I prefer the first. – Weather Vane Oct 10 '20 at 17:43
  • the actual syntax for `malloc()` in C is: `void *malloc(size_t size);` I suspect your confusing C with C++ – user3629249 Oct 12 '20 at 04:29

2 Answers2

3

That's because when declaring a pointer the "*" is on the left, not on the right.

The * is on the right of the type name. In void *p = &a; type is void *, a void pointer. It is on the left of the thing it's being applied to, the variable p.

In ptr = (cast-type*) malloc(byte-size) the type is cast-type *, the * is to the right of the type name. The cast is on the left of the thing being cast, the call to malloc, like an adjective.

[I do find it odd that we write type *variable, which makes it seem like the * is part of the variable rather than type* variable which puts the * with the type.]

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • 1
    Yes, but when you write `type* variable, anothervar;` only `variable` is a pointer. Writing `type *variable, anothervar;` makes it clear. – Weather Vane Oct 10 '20 at 18:36
  • 1
    *I do find it odd that we write `type *variable`, which makes it seem like the `*` is part of the variable rather than `type* variable` which puts the `*` with the type.* Because the `*` ***IS*** with the variable. `int* a, b` makes `b` an `int`, ***NOT*** an `int *`. – Andrew Henle Oct 10 '20 at 18:36
  • @Schwern: There are good reasons to declare variables separately, but working around bad practice isn’t one of them. `*` is part of the declarator, period. Pretending it isn’t leads to confusion and inconsistency. A declaration like `int* a[10];` is schizophrenic. And it doesn’t work for pointers to arrays or pointers to functions. – John Bode Oct 10 '20 at 21:54
0

The * indirection operator is a unary operator, meaning its operand is to the right of the operator, as in *p.

C declarations are broken into two major sections - a sequence of declaration specifiers (type specifiers, storage class specifiers, type qualifiers, etc.) followed by a comma-separated list of declarators. A declarator introduces the name of the thing being declared, along with information about that thing’s array-ness, pointer-ness, and function-ness. In the declaration statement

int a[10], *p, f(void);

the declaration specifier is int and the declarators are a[10], *p, and f(void). Note that the * is bound to the declarator, not the type specifier. Because it’s a unary operator and token on its own, you don’t need whitespace to separate the type specifier from the identifier - all of

int *p;
int* p;
int*p;
int     *      p;

are equally valid, and all are interpreted as int (*p); - the operand of * is always p, not int or any other type specifier1.

The type of a is "10-element array of int", which is fully specified by the combination of the int type specifier and by the [10] in the declarator. Similarly the type of p is "pointer to int", which again is fully specified by the combination of the type specifier and the * operator in the declarator. And the type of f is "function returning int" by the same reasoning.

This is key - there is no type specifier for pointer, array, or function types - they can only be specified by a combination of one or more declaration specifiers and a declarator.

So how do we specify pointer types (or array or function types) in a cast? Basically, we write a declaration composed of declaration specifiers and a declarator, but with no identifier. If we want to cast something as a pointer to int, we write it as a regular pointer declaration with an unnamed variable - (int *).


  1. This is why I’m not fond of the C++ convention of writing pointer declarations as T* p;; it doesn’t follow the syntax, and it’s inconsistent - a declaration like int* a[N]; is schizophrenic. It also introduces confusion when you write something like T* p, q; because it looks like you intend to declare both p and q as pointers, but only p is.
John Bode
  • 119,563
  • 19
  • 122
  • 198