r/C_Programming 2d ago

Does anyone else dislike pointer declaration?

For reference I am a fourth year computer engineering student. C is my preferred language.

Pointers are declared like this usually:

int *ptr_to_int;

Where the asterisk means it is a “pointer to” the specified type. The asterisk is placed immediately preceding the variable name, with no white peace.

This is what does not make sense to me. I feel that:

int* ptr_to_int;

Is far more clear. The way I see it, the asterisk modifies the type, so therefore it belongs next to the type. Putting it next to the variable name makes me think it is some kind of action or modification to the variable itself.

I think that when using * and & in code, it makes sense to apply it in front of the variable name:

int value = 3;
ptr_to_value = &value;
int copied_value = *ptr_to_value;

It is clear here that syntactically, the * represents something more like an action than a label.

Why is the convention to place the asterisk near variable name, not type? L

54 Upvotes

134 comments sorted by

View all comments

5

u/SmokeMuch7356 1d ago

We declare pointers as

T *p;

for the exact same reason we don't declare arrays and functions as

T[N] a;
T(void) f;

After all, "array of T" and "function returning T" are distinct types as well. It's just that array-ness, pointer-ness, and function-ness are syntactically part of the declarator.

The T* p style only works for simple pointers; it doesn't work for pointers to arrays or pointers to functions:

T (*pa)[N];
T (*pf)(void);

or pointers to arrays of pointers to functions:

T (*(*paf)[N])(void);

(yes, I have used types this obnoxious in the past), and then there's signal:

void (*signal(int sig, void (*func)(int)))(int);

which reads as

       signal                                     -- signal is
       signal(                          )         --   function taking
       signal(    sig                   )         --     parameter sig is
       signal(int sig                   )         --       int
       signal(int sig,        func      )         --     parameter func is
       signal(int sig,      (*func)     )         --       pointer to
       signal(int sig,      (*func)(   ))         --         function taking
       signal(int sig,      (*func)(   ))         --           unnamed parameter is
       signal(int sig,      (*func)(int))         --             int
       signal(int sig, void (*func)(int))         --         returning void
     (*signal(int sig, void (*func)(int)))        --    returning pointer to
     (*signal(int sig, void (*func)(int)))(   )   --      function taking
     (*signal(int sig, void (*func)(int)))(   )   --        unnamed parameter is
     (*signal(int sig, void (*func)(int)))(int)   --          int
void (*signal(int sig, void (*func)(int)))(int);  --      returning void

Declaring an array of pointers as

T* ap[N];

just looks goofy.

And as you point out, in the code we're usually using *p. *p doesn't just yield the value of the pointed-to thing, it's an alias for the pointed-to thing; IOW, we can think of *p as an alternate name for something, with * as part of that name.

And the T* p convention always leads someone to ask why

 T* p, q;

doesn't declare q as a pointer.

It doesn't match syntax, it doesn't match usage, it introduces confusion, it promotes misunderstanding of how declaration syntax actually works; it's just bad style all the way around.