Question

As I read in the c standards an adress-constant is to be qualified this way:

int * const ptr,

I was asking my self, would work int const i too, instead of const int i.

And it did.

After I noticed they were equal I was just trying a bit arround, to get the point of const's behaving. I did stuff like

int * const * pPtr and int const * ptr in different compilers, I notified, they all treat const, as if the definition would be:

"const qualifies the type to its left, just as there is no type to its left, it shall quallifie the right part"

But I could not find anything about this in the standards. And each example in the standard is written with const at beginning of the declaration or just behind the static part.

(What at least wouldn't refuse my suggestion...)

So why allmost everyone uses the const at beginning of declaration, as it would be more intelligible the way I mentioned?

And how to qualifie an identifier correctly as const, according to the assumption compilers are supporting both ways?

Was it helpful?

Solution

So why almost everyone uses the const at beginning of declaration, as it would be more intelligible the way I mentioned?

It's just a coding style, both valid syntax.

C11 §6.7 Declarations

Syntax

declaration:

declaration-specifiers init-declarator-listopt ;

static_assert-declaration

declaration-specifiers:

storage-class-specifier declaration-specifiers opt

type-specifier declaration-specifiers opt

type-qualifier declaration-specifiers opt

function-specifier declaration-specifiers opt

alignment-specifier declaration-specifiers opt

init-declarator-list:

init-declarator

init-declarator-list , init-declarator

init-declarator:

declarator

declarator = initializer

Notice the lines I use bold, type-specifier are keywords like int, char or void, etc. type-qualifier are keywords like const volatile etc.

According to the standard, declaration-specifiers are defined recursively, that's why const int i and int const i are both valid:

       int            const       i;
//      |               |
//type-specifier  type-qualifier 
//      \______________/  
//             |
//     declaration-specifier

      const               int       i;
//      |                  |
//      |            type-specifier 
//      |                  |
//type-qualifier  declaration-specifier
//      \__________________/  
//                |
//        declaration-specifier

OTHER TIPS

Rule of thumb: Moving const over a * makes a difference. Otherwise it doesn't.

Wow, there is a lot of 'const' going on.


int * const foo1

foo1 is a "const pointer to int". The value of foo1 is constant. What foo1 points to may change.


int const foo2
const int foo3

foo2 and foo3 are the same type - both are correct - C allows both. the order of int and const is a style choice. In both cases, the identifier is constant. Having const first is more common in my experience. Thus I tend to follow prior art. Further - I find either OK as long as it is consistent with a module. In both cases, one would expect to find an initializer like const int foo3 = 7;


But also some unraveling of confusion is needed.
[Edited answer follows]

// OP's experimented with these
int * const * foo4;
int const * foo5;

OP surmised with "const qualifies the type to its left, just as there is no type to its left, it shall quallifie the right part". This is explainable for these 2 and appears to apply to additional samples:

foo4 is a "pointer to const pointer to int".
foo5 is a "pointer to const int".

Additional samples:

int * const foo6;
const int* foo7;
int const * const foo8;

foo6 is a "const pointer to int".
foo7 is a "pointer to const int" - same as foo5.
foo8 is a "const pointer to const int".

foo6 is constant, the data it points to is not constant.
foo7 is not constant, the data it points to is treated as constant.
foo8 is constant. The data it points to is treated as constant.

@ugoren is correct in the post about moving the const across a *. Moving the const changes the type. That is not a style difference, but different code.


Ref:

C11 6.2.5.29 "EXAMPLE 1 The type designated as ‘‘float *’’ has type ‘‘pointer to float’’. Its type category is pointer, not a floating type. The const-qualified version of this type is designated as ‘‘float * const’’ whereas the type designated as ‘‘const float *’’ is not a qualified type — its type is ‘‘pointer to const-qualified float’’ and is a pointer to a qualified type."

C11 6.7

http://cdecl.org/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top