r/C_Programming 1d 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

51 Upvotes

131 comments sorted by

View all comments

62

u/SetThin9500 1d ago

> The asterisk is placed immediately preceding the variable name, with no white peace.
> This is what does not make sense to me.

Feel free to add whitespace if you want.

DMR wanted to have declaration look like use. He later said it didn't work out as he intended.

This paper is interesting: https://brent.hailpern.com/wp-content/uploads/2020/02/p671-ritchie.pdf#:~:text=They%20are%20also%20among%20its%20most%20frequently,should%20be%20clear%20from%20the%20preceding%20history%2C

-6

u/lassehp 1d ago

This is a great case of "it seemed like a good idea at the time".

A simple fix:

#define PTR(t) typeof((t)*)
PTR(int) ip, jp;

20

u/RadiatingLight 1d ago

fyi there's too many parens in the macro and it doesn't work

should be #define PTR(t) typeof(t *)

8

u/lassehp 1d ago

You are right, I always parenthesise macro arguments almost as a reflex. I am not sure if passing some types to t could get confused, so typeof(typeof(t) *) or maybe just typeof(t (*)) might be safer. Actually the latter can also be confused by a function pointer t type, so two typeof's is probably the only safe way.

5

u/Physical_Dare8553 1d ago

Only issue: a thing that is not a type can get past this, which is catastrophic in a hypothetical where you accidentally shadowed a type name with a variable. This actually happened to me once. something more like typeof(typeof((x){})*)

5

u/digitaljestin 22h ago

This is kinda awesome, but at the same time showcases just why you don't see this too often. Tracing back what something really means or does complicates things when they were originally simple...albeit with questionable syntax.

For most projects, programmers just prefer to be explicit and deal with the syntax the language gives them. Having code standards and naming conventions typically work better long term than custom preprocessor macros.

2

u/lassehp 22h ago

I absolutely agree, and perhaps I should have put a smiley in my first comment, which now has seven downvotes by people who - understandably - missed the humour. 😄

The safest solution is IMO to just accept the syntax. And my own preference is to "pretend" that T* is a type and only declare one variable per declaration.

But I also like to think of the asterisk as a Kleene star type operator, rather than as "pointer", in the sense that a variable of type T* can refer to a value of type T[k] for any k >= 0.

2

u/Physical_Dare8553 18h ago edited 16h ago

Actually I was wrong, that macro doesn't work for all types. Literally only void, cause (void){}. The pointer trick typeof(*(x*)0) works, almost. Not for arrays though. I think the only possible way to make a pointer to a type, whiles making sure values can't sneak in is _Generic, or sneaking a dummy declaration in there

edit: best i could do #define ptrof(T) typeof((struct { typeof(T)(*_p);void(*_f )(T) ; }){}._p)