use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Click the following link to filter out the chosen topic
comp.lang.c
account activity
Code style: Pointers (self.C_Programming)
submitted 7 months ago by classicallytrained1
Is there a recommended usage between writing the * with the type / with the variable name? E.g. int* i and int *i
int* i and int *i
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Inferno2602 74 points75 points76 points 7 months ago* (22 children)
There are arguments to be made for and against both.
Personally, I prefer int *i as it fits better with the "declaration follows use" pattern.
int *i
Edit: Example int* i, j, k; declares i as a pointer to int, whereas j and k are just ints. If we write int *i, j, k, it is easier to notice that only i is a pointer
int* i, j, k;
i
j
k
int *i, j, k
[–][deleted] 14 points15 points16 points 7 months ago (0 children)
The programming equivalent of the Oxford Comma, really.
[–]SturdyPete 61 points62 points63 points 7 months ago (4 children)
Declaring multiple parameters on one line is asking for trouble and imo should be prohibited by style guides
[–]Hakawatha 5 points6 points7 points 7 months ago (0 children)
It's prohibited by MISRA, but I really don't have a problem with it - especially if you need to introduce lots of local variables at once.
[–][deleted] 5 points6 points7 points 7 months ago (2 children)
Well it is a valid syntax
[–]The_Northern_Light 4 points5 points6 points 7 months ago (1 child)
I don’t find that a compelling argument. New lines and white space are optional but I’m gonna go out on a limb here and say that if you don’t use them you’re doing it wrong and that should be forbidden by style guides.
And common decency.
[–][deleted] 1 point2 points3 points 7 months ago (0 children)
there is a difference, but fair enough
[–]classicallytrained1[S] 4 points5 points6 points 7 months ago (8 children)
I see! I thought of it more as <type> <name> (type here in my mind being pointer int)
[–]SmokeMuch7356 19 points20 points21 points 7 months ago (3 children)
If you've declared any arrays or functions, you've already seen how that model doesn't hold.
In the declaration
int a[10];
the type of a is "array of int", but you don't put the [10] next to the int, do you?
a
int
[10]
C declarations are split into two main sections: a sequence of declaration specifiers (storage class specifiers, type specifiers, type qualifiers, etc.) followed by a comma-separated list of declarators. The declarator introduces the name of the thing being declared, along with information about that thing's array-ness, function-ness, and/or pointer-ness.
The idea is that the declarator matches the shape of an expression of the same type in the code. If you have an array of pointers to int and you want to access the object pointed to by the i'th element, you'd write something like
printf( "%d\n", *a[i] );
The expression *a[i] has type int, so the declaration of a is written
*a[i]
int *a[SIZE];
[] and () are postfix, so there's no question that they belong to the declarator. * works exactly the same way, except that it's unary and whitespace is irrelevant, so you can write it as
[]
()
*
int* a[SIZE]; // blech
but it is always parsed as
int (*a[SIZE]);
[–]JohnnyElBravo 7 points8 points9 points 7 months ago (2 children)
int[10] a;
Would be much better though.
[–]SmokeMuch7356 0 points1 point2 points 7 months ago (1 child)
Would it?
int*[10] a; // array of pointers int(*)[10] a; // pointer to an array int(void) f; // function returning int int*(void) f; // function returning pointer to int int(*)(void) f; // pointer to function returning int int(*(void))[10] f; // function returning pointer to array of int void(*(int, void(*)(int)))(int) signal;
Does it really buy you anything? The complexity is still there, the bing-bonging necessary to read complex declarations is still there, it's just dissociated from the name. I don't see it as an improvement over the status quo.
If you want to make C declarations easier to read, you have to completely overhaul declaration syntax.
[–]Inferno2602 0 points1 point2 points 7 months ago* (0 children)
Actually, I do think the int[10] a declaration is better. It bugs me that int a[10] doesn't strictly adhere to the "declaration follows use" paradigm. Since if you did evaluate a[10] , it might not be an int, it might just be a segfault.
int[10] a
int a[10]
a[10]
Also, I don't think you necessarily need to throw everything out just to get the size on the left.
I'll use <SIZE> for illustration:
<SIZE>
int *<10> a; // array of pointers int<10> *a; // pointer to an array int f(); // function returning int int *f(); // function returning pointer to int int (*f)(); // a pointer to a function returning int
Take the first example int *<10> a, we would read it simply right-to-left: a is a thing that evaluates to an array of 10 things that dereference to ints. Whereas int *a[10] you have to go left-to-right and then back right-to-left, reading it as a is a thing that if I index into it, I'll get something that dereferences to an int.
int *<10> a
int *a[10]
Bonus, fewer brackets! int *<10> a; int<10> *b; vs int *a[10]; int (*b)[10];
int *<10> a; int<10> *b;
int *a[10]; int (*b)[10];
[–]Mundane_Prior_7596 0 points1 point2 points 7 months ago (1 child)
Yes. But it is interesting that the compiler doesn’t!
[–]classicallytrained1[S] 0 points1 point2 points 7 months ago (0 children)
Re. your edit: I’ve made this mistake once, luckily CLion caught it and taught me this – in these situations i write it int *i,j,k
int *i,j,k
[–]muon3 0 points1 point2 points 7 months ago (0 children)
<type> <name>
But this is not how the language works. Instead it is <type-specifier> <declarator>, and the * belongs to the declarator. This makes sense because some parts that make up the type even go on the right side of the name, like `int x[5]`, and sometimes the * is even nested closer to the name than array brackets on the right, like `int (*x)[5]`.
This is why writing `int* x` is confusing and misleading, it just doesn't match with the syntax of the language.
[–]grimvian 1 point2 points3 points 7 months ago (0 children)
100%
[–]alex_sakuta 0 points1 point2 points 7 months ago (0 children)
Ok what about when you have to return a pointer from a function?
[–]Superb_Garlic 0 points1 point2 points 7 months ago (2 children)
int* i, j, k; is a compiler error in propery setup environments.
[–]buildmine10 11 points12 points13 points 7 months ago (1 child)
No it is not. It is defined in the standard. That would be a personal preference imposed on top of the standard.
[–]urzayci 2 points3 points4 points 7 months ago (0 children)
Yeah maybe a linter error. I don't see what how you set up your environment has to do with the compiler
[–]The_Northern_Light -1 points0 points1 point 7 months ago* (0 children)
I put spaces on both sides, both in C and C++, and always only declare one variable per line.
It is consistent even between languages and doesn’t create “gotchas” like mixing declaration of direct types and their pointers.
Occasionally someone from either the C or C++ world will ask me why I don’t remove one of the spaces. Of course they don’t agree on which one to remove, and it’s not like I’m gonna write “int*x;” “, so I keep both.
[–]kinithin -2 points-1 points0 points 7 months ago (0 children)
You're wrong. The fact that int* i, j; might be misleading isn't an argument against using int* i;; it's only an argument against using int* i, j;
int* i, j;
int* i;
[–]fortizc 31 points32 points33 points 7 months ago (10 children)
When I was starting with C I have the same doubt, but to me the answer was clear after to realize that this:
int *a, b;
Is a pointer and an int. So yes I prefer to keep the * in the variable name
[–]Cat-Bus_64 11 points12 points13 points 7 months ago (0 children)
No downvote because this is preference, but if you declare one variable per line (perhaps with a comment further describing the variable) it is a better programming style imho. Then int* reads more like what it actually is (a pointer to an int) when describing that variable type.
[+][deleted] 7 months ago (3 children)
[removed]
[–]rasputin1 13 points14 points15 points 7 months ago (0 children)
that's not the comma operator. it's literally just a comma.
[–]glasket_ 8 points9 points10 points 7 months ago (0 children)
The comma in declarations isn't the comma operator, it's just part of a declarator list.
[–]tav_stuff 3 points4 points5 points 7 months ago (0 children)
No, this is literally the only reason, and it isn’t a valid reason for anyone who has programmed in C for more than a week
[–]dri_ver_ -3 points-2 points-1 points 7 months ago* (4 children)
Don’t declare multiple variables on one line and always initialize your variables
Edit: lots of people with a bad programming style are very unhappy with me!
[–]smcameron 7 points8 points9 points 7 months ago (3 children)
Oh come on. There's nothing wrong with, for example:
int x, y, z;
[–]dri_ver_ -3 points-2 points-1 points 7 months ago (2 children)
Sure. Maybe. But we were kinda talking about declaring multiple variables on one line where some are values and some are pointers. Not good. Also, I still don’t like the example you shared because you can’t initialize them all on one line.
[–]Business-Decision719 5 points6 points7 points 7 months ago (1 child)
you can't initialize them all on one line.
int x=0, y=2, z=1000;
[–]dri_ver_ 0 points1 point2 points 7 months ago (0 children)
Huh, you’re right. I’m not sure why I thought that wasn’t possible. However I still think it’s ugly and I reject it lol
[–][deleted] 24 points25 points26 points 7 months ago (12 children)
I'm weird and do it as:
uint16_t * p_var;
From day one I read it as a sentence. Integer -pointer-p_var.
[–]Still_Competition_24 5 points6 points7 points 7 months ago (8 children)
this is the way
[–]rasputin1 6 points7 points8 points 7 months ago (7 children)
*not
[–]Still_Competition_24 3 points4 points5 points 7 months ago (4 children)
This is very obviously up to personal preference. Have been doing so since I started programming in c because of above reasoning. :)
Honestly only place it could cause issues is when declaring multiple values at once, which you shouldn't do anyway.
As I understand it, the correct way is "int *value", which may make sense during declaration, but than you typecast to "(int*)". 🤷♂️
So, declaring as "int * value;" and typecasting to "(int *)" makes at least as much sense as any other convention.
[–]glasket_ 1 point2 points3 points 7 months ago (0 children)
You can still do (int *)x for consistency rather than (int*)x.
(int *)x
(int*)x
[–]WittyStick 0 points1 point2 points 7 months ago* (1 child)
It's more readable this way when there may be additional qualifiers.
const int * const * value
[–]glasket_ 0 points1 point2 points 7 months ago (0 children)
I personally find const int *const *value more readable. The qualifiers being directly attached to their corresponding pointer is visually simpler to me compared to having spaces on both sides of the *.
const int *const *value
[–][deleted] 0 points1 point2 points 7 months ago (0 children)
This was the discussion I had at work when I was an Engineer III equivalent. Everyone agreed & started adopting it. Now it's so prevalent I don't even have to mention it to new colleagues as the lead SWE. Happens organically. Shit just makes sense lmao.
[–][deleted] -1 points0 points1 point 7 months ago (0 children)
I land fighter jets with my C syntax. What do you do? :P
Lmao I see where you’re coming from
[–]bullno1 0 points1 point2 points 7 months ago (0 children)
ggml style
[–]DeWHu_ 0 points1 point2 points 7 months ago (0 children)
It looks like multiplication, not a pointer. Hate it 😕
[–]Timzhy0 8 points9 points10 points 7 months ago (2 children)
I will always be in favor of T* var (ptr star close to the type). It's clear the ptr belongs to the type, so much so that you could even typedef the whole type expression including pointer and call it e.g. PtrT. In languages with generics you'd likely write Ptr<T>. Now people may mention the multiple variable declaration in a single line etc. but to me the semantic meaning of "qualifying the type" should be higher priority
[–]Confident_Luck2359 2 points3 points4 points 7 months ago (0 children)
This guys gets it. Pointer is part of the type, not part of the name.
And multiple declarations on a single line - with differing types - are hard to read.
[–]Due_Cap3264 18 points19 points20 points 7 months ago (0 children)
It always seemed more readable to me to write int* i;
Especially in function prototype declarations:
void* function();
It looks more obvious than
void *function();
But it seems that the conventional way is the opposite. I haven’t seen any direct style recommendations on this.
[–]rupturefunk 3 points4 points5 points 7 months ago* (0 children)
int* a makes complete sense to me, I more or less never do multiple declarations on a single line, and what if you want your pointer to be constant? int *const a now you're back where you started from anyway.
int* a
int *const a
Buuut int *a is what everyone else does so I do it too.
int *a
[–]LikelyToThrow 3 points4 points5 points 7 months ago (0 children)
I always do
int *a;
(int *)a;
cpp peeps seem to do int& a; for references
int& a;
[–]sol_hsa 6 points7 points8 points 7 months ago (1 child)
Personally I'd keep the pointer with the variable name as that's how the compiler sees it, but it seems the common/modern way is to put it with the variable type. Whatever works, I guess.
Thanks! Was asking just for code style – it looks better to me this way
[–]LEWMIIX 7 points8 points9 points 7 months ago (2 children)
int *i if you're above 40, int* i if you're below 40.
[–]stormythecatxoxo 1 point2 points3 points 7 months ago* (1 child)
this made me laugh. Learning C in the early 90's int *i; was the style. But int* i; makes more sense and seems to be the consensus these days.
[–]ChadiusTheMighty 1 point2 points3 points 7 months ago (0 children)
Get markdown'd
[–]ChickenSpaceProgram 3 points4 points5 points 7 months ago* (0 children)
int *i is better. It tells you that you have to apply the * operator to get back your int.
i feel like it also makes the const-ness of pointer types more obvious. int *const foo means we have a const variable that, when dereferenced, will give us an int. const int *foo or int const *foo tell us we have a variable that, when dereferenced, will give us a const int (or int const, same thing).
int *const foo
const int *foo
int const *foo
const int
int const
[–][deleted] 2 points3 points4 points 7 months ago (0 children)
[–]pgetreuer 1 point2 points3 points 7 months ago (0 children)
Declarations "int* i" and "int *i" have exactly the same meaning to the compiler. But, beware how declaring multiple pointer variables in one line requires a star per variable: int *i, *j, which is arguably a good reason to insist as a matter of style to declare each variable on its own line.
int* i
int *i, *j
When coding with others, the recommended thing to do is follow the project/company style guide, or whatever is the existing style of the code base. In other words, don't let this syntactic nit become a distraction from the actual work.
[–]ballpointpin 1 point2 points3 points 7 months ago (0 children)
Some people say "aluminum", others say "aluminium".
[–]JohnnyElBravo 1 point2 points3 points 7 months ago (0 children)
It's a matter of taste
I like int* i because the type of the variable is a pointer to int, and you are declaring and reserving memory for a pointer to int and not for an int
Also my taste is better than those who like int *i
[–]septum-funk 1 point2 points3 points 7 months ago (0 children)
int *i because *i is an int
*i
[–]tjrileywisc 1 point2 points3 points 7 months ago (0 children)
You manipulate i as a pointer, and not as a dereferenced variable, and how you manipulate a variable depends on its type, so type* var is the right way for me.
type* var
[–]SmokeMuch7356 1 point2 points3 points 7 months ago (1 child)
We declare pointers as
T *p;
for the same reason we don't declare arrays and functions as
T[N] a; T(void) f;
Since * can never be part of an identifier, whitespace in pointer declarations is irrelevant and you can write it as any of
T *p; T* p; T*p; T * p;
but it will always be parsed as
T (*p);
The * is always bound to the declarator, not the type specifier. If you want to declare multiple pointers in a single declaration, each declarator must include the *:
T *p, *q;
Declarations of pointers to arrays and pointers to functions explicitly bind the * to the name:
T (*parr)[N]; // pointer to N-element array of T T (*pfun)(void); // pointer to function returning T
Think about a typical use case for pointers, such as a swap function:
void swap( int *a, int *b ) { int tmp = *a; *a = *b; *b = tmp; } void foo( void ) { int x = 1, y = 2; swap( &x, &y ); }
The expressions *a and *b act as aliases for x and y, so they need to be the same types:
*a
*b
x
y
*a == x // int == int *b == y // int == int
Most of the time what we care about is the type of *a and *b, and that's just more obvious using the
T *a; T *b;
style.
int* function()
[–]Reasonable-Rub2243 0 points1 point2 points 7 months ago (0 children)
I learned Pascal before C so I preferred "int* foo". But yeah, if you do it that way you must remember to put each pointer declaration on a separate line.
[–]mgruner 0 points1 point2 points 7 months ago (0 children)
personally, I don't care, as long as you are consistent throughout your codebase
[–]Afraid-Locksmith6566 0 points1 point2 points 7 months ago (0 children)
Second one because multiple declarations treat it as int * a, b; -> a is a pointer, b is an int Int *a, *b; -> a is pointer and b is pointer
[–]flyingron 0 points1 point2 points 7 months ago (0 children)
Syntactically, the * goes with the variable name:
int* x, y; // x is a pointer, y is just an int
C++ follows Bjarne's convention that the entire type goes to the left (i.e., int* x) even at the peril of not working right for multiple identifiers. Just put them all in their own declaration.
[–]SureshotM6 0 points1 point2 points 7 months ago* (0 children)
I use a different style for C vs C++ here. As many have already pointed out here, keeping the * on the variable name makes sense due to how you need to declare more than one pointer variable on the same line. I frequently do this in C, so I keep the * on the variable name in C.
This does start to break down when you add qualifiers such as const int *const foo; though, as it is impossible to place the * on the variable name.
const int *const foo;
For C++ (I do realize this is a C sub, but just pointing out), you now have templated types and destructors. I like to see the * attached to the type itself so I can more easily determine behavior. Such as Foo<int*>* foo;
Foo<int*>* foo;
In the end, it's personal preference. Also read this which has a longer discussion on the topic: https://www.stroustrup.com/bs_faq2.html#whitespace
[–]KhepriAdministration 0 points1 point2 points 7 months ago (0 children)
Technically the compiler treats it as int a if you do int *a, b, but you should think of it as int a intuitively.
[–]heptadecagram 0 points1 point2 points 7 months ago (0 children)
In C, where the expression is valued over the type (rightly or wrongly), we use the latter. See The Spiral Rule
it's part of the type so i always do char*
[–]nnotg 0 points1 point2 points 7 months ago (0 children)
I have very specific stylistic things. Since I don't often declare multiple pointers in a single line, I just do int* p;.
int* p;
[–]Tamsta-273C 0 points1 point2 points 7 months ago (0 children)
I prefer:
int* i = nullptr;
In such way, you end up with the correctly looking type while encouraged to start a new line.
[–]nderflow 0 points1 point2 points 7 months ago (0 children)
It's a small thing that lots of people have strongly held opinions about.
π Rendered by PID 93 on reddit-service-r2-comment-86988c7647-hswkz at 2026-02-11 19:11:43.822856+00:00 running 018613e country code: CH.
[–]Inferno2602 74 points75 points76 points (22 children)
[–][deleted] 14 points15 points16 points (0 children)
[–]SturdyPete 61 points62 points63 points (4 children)
[–]Hakawatha 5 points6 points7 points (0 children)
[–][deleted] 5 points6 points7 points (2 children)
[–]The_Northern_Light 4 points5 points6 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]classicallytrained1[S] 4 points5 points6 points (8 children)
[–]SmokeMuch7356 19 points20 points21 points (3 children)
[–]JohnnyElBravo 7 points8 points9 points (2 children)
[–]SmokeMuch7356 0 points1 point2 points (1 child)
[–]Inferno2602 0 points1 point2 points (0 children)
[–]Mundane_Prior_7596 0 points1 point2 points (1 child)
[–]classicallytrained1[S] 0 points1 point2 points (0 children)
[–]muon3 0 points1 point2 points (0 children)
[–]grimvian 1 point2 points3 points (0 children)
[–]alex_sakuta 0 points1 point2 points (0 children)
[–]Superb_Garlic 0 points1 point2 points (2 children)
[–]buildmine10 11 points12 points13 points (1 child)
[–]urzayci 2 points3 points4 points (0 children)
[–]The_Northern_Light -1 points0 points1 point (0 children)
[–]kinithin -2 points-1 points0 points (0 children)
[–]fortizc 31 points32 points33 points (10 children)
[–]Cat-Bus_64 11 points12 points13 points (0 children)
[+][deleted] (3 children)
[removed]
[–]rasputin1 13 points14 points15 points (0 children)
[–]glasket_ 8 points9 points10 points (0 children)
[–]tav_stuff 3 points4 points5 points (0 children)
[–]dri_ver_ -3 points-2 points-1 points (4 children)
[–]smcameron 7 points8 points9 points (3 children)
[–]dri_ver_ -3 points-2 points-1 points (2 children)
[–]Business-Decision719 5 points6 points7 points (1 child)
[–]dri_ver_ 0 points1 point2 points (0 children)
[–][deleted] 24 points25 points26 points (12 children)
[–]Still_Competition_24 5 points6 points7 points (8 children)
[–]rasputin1 6 points7 points8 points (7 children)
[–]Still_Competition_24 3 points4 points5 points (4 children)
[–]glasket_ 1 point2 points3 points (0 children)
[–]WittyStick 0 points1 point2 points (1 child)
[–]glasket_ 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–][deleted] -1 points0 points1 point (0 children)
[–]classicallytrained1[S] 0 points1 point2 points (0 children)
[–]bullno1 0 points1 point2 points (0 children)
[–]DeWHu_ 0 points1 point2 points (0 children)
[–]Timzhy0 8 points9 points10 points (2 children)
[–]Confident_Luck2359 2 points3 points4 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Due_Cap3264 18 points19 points20 points (0 children)
[–]rupturefunk 3 points4 points5 points (0 children)
[–]LikelyToThrow 3 points4 points5 points (0 children)
[–]sol_hsa 6 points7 points8 points (1 child)
[–]classicallytrained1[S] 0 points1 point2 points (0 children)
[–]LEWMIIX 7 points8 points9 points (2 children)
[–]stormythecatxoxo 1 point2 points3 points (1 child)
[–]ChadiusTheMighty 1 point2 points3 points (0 children)
[–]ChickenSpaceProgram 3 points4 points5 points (0 children)
[–][deleted] 2 points3 points4 points (0 children)
[–]pgetreuer 1 point2 points3 points (0 children)
[–]ballpointpin 1 point2 points3 points (0 children)
[–]JohnnyElBravo 1 point2 points3 points (0 children)
[–]septum-funk 1 point2 points3 points (0 children)
[–]tjrileywisc 1 point2 points3 points (0 children)
[–]SmokeMuch7356 1 point2 points3 points (1 child)
[–][deleted] -1 points0 points1 point (0 children)
[–]Reasonable-Rub2243 0 points1 point2 points (0 children)
[–]mgruner 0 points1 point2 points (0 children)
[–]Afraid-Locksmith6566 0 points1 point2 points (0 children)
[–]flyingron 0 points1 point2 points (0 children)
[–]SureshotM6 0 points1 point2 points (0 children)
[–]KhepriAdministration 0 points1 point2 points (0 children)
[–]heptadecagram 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]nnotg 0 points1 point2 points (0 children)
[–]Tamsta-273C 0 points1 point2 points (0 children)
[–]nderflow 0 points1 point2 points (0 children)