Fog Creek Software
Discussion Board




weird (?) declaration

Hey all,

I noticed the following in someone's code:

int foo(int * const ptr, ...)

Now, this doesn't make any sense to me. It's like:

int foo(const int var)

What's the use ?

I would go on and say that it's a mistake (maybe he meant "const int* ptr"), but it's an experienced developer.

So any ideas ?

The only one I have is to prevent himself from changing that ptr, but what harm would it make ?!?!

Eli Bendersky
Friday, June 04, 2004

I'm not a C++ developer, but is this relevant?

I post this to test my own knowledge, rather than to answer your question.

http://www.relisoft.com/book/lang/pointer/6list.html

The comments at the bottom of the page where it discusses the declaration:

"Link * const pLink;" translates to "Link is a constant pointer to link."

"Link const * pLink;" translates it to "Plink is a pointer to a constant link."

If I have this right, then you colleague is declaring the variable as a constant pointer to an int.  That is, the value passed into the paramater (pushed onto the stack) is the memory address of a variable that contains an integer value.  The value of this address cannot be changed within the function.

On the other hand, with your declaration you are stating that the paramater pushed onto the stack will be be integer variable, and that integer variable does not change.

Ged Byrne
Friday, June 04, 2004

Testing further:

int foo(const int var)

If this declaration was used instead then the value of var would be lost after the execution.  If the value of var was changed within the function then that new value would be lost.

const int * ptr

If this decalaration was used instead it would not be possible to change the value stored at the address pointed to by pointer.  You could change the pointer to point elsewhere, but you still could not change its target.

By declaring as "int foo(int * const ptr, ...)" the developer has ensured that:

1)  The target variable for ptr will be available after the function has finished.

2)  If, at any pointer, the function updates the target of ptr, he can be sure that this is the one he expects since ptr is constant.

Do I understand correctly?

Ged Byrne
Friday, June 04, 2004

"If, at any point"

Ged Byrne
Friday, June 04, 2004

I think you miss something guys... I understand perfectly the various "const" semantics in C++ (heck, I even wrote a short tutorial about it: http://www.geocities.com/spur4444/prog/const_and_pointers.html).

The default passing of variables in C and C++ is by value, on the stack. This means that if the called function changes the argument, it doesn't affect the caller - it's just a temporary stack value. Thus the following declaration doesn't protect the caller:

int foo(const int var)

Any more than:

int foo(int var)

A common way to protect the caller is passing constant pointers or references to some function, liek this:

int foo(const int* ptr)

This way, foo can't change what ptr points to, as it could in:

int foo(int* ptr)

foo can change "ptr" itself, but exactly as "var" in the previous example, it's just a stack temporary, so it doesn't harm the caller.

So, declaring:

int foo(int* const ptr)

Doesn't add any protection over:

int foo(int* ptr)

Thus it's weird. I'm into C/C++ for many years, and it's the first time I saw such a declaration in code.

Eli Bendersky
Friday, June 04, 2004

Yes, Eli, you are right.

It appears whoever wrote this declaration had a temporary moment of higher insight :)  If you say he was a experienced programmer, I'd bet one day he will himself wonder about what he tried to accomplish by that declaration.

Regards,

chance

chance
Friday, June 04, 2004

Try to compile this:

void foo(int* const ptr)
{
    ptr = 0;
}

void bar(const int* ptr)
{
    delete ptr;
}

and you will see why he has done it. His version stops him, by mistake, assigning a value to the pointer instead of the int (i.e. instead of *ptr = <value> he might write ptr = <value> instead, like above).


Friday, June 04, 2004

So let him assign "ptr = 0", what harm does it make ?

If you declare local pointers in your function, do you do:

int* const ptr = new int(88);

???

If not, why not ? It would prevent you from assigning to them later.

The variables a function receives on stack are this functions' property, it may do whatever it likes with them. It's considered bad style, perhaps, to change them, but it's also considered bad style to fill your program with useless const's.

Eli Bendersky
Friday, June 04, 2004

And your second function is irrelevant.

const int* ptr

makes a lot of sense, and should be ALWAYS used, unless the ptr is passed explicitly to be changed, in which case, it's good practice to define some empty OUT macro and write:

int foo(OUT int* ptr) // now I know ptr will be changed

Eli Bendersky
Friday, June 04, 2004

I'm not so sure about this macro approach. Personally I think it's fine to stick to the idiom that when passing pointers to a function, you declare them to point at constant value and when they are meant to be explicitly changed, you just leave that "const" out of the declaration.

Same goes for references, naturally. I believe it's called part of the concept of "const correctness".

Regards,

chance

chance
Friday, June 04, 2004

Eli,

I suspected that I was missing something, which is why I wanted to test my knowledge.

I have to say, this confirms my choice not to use C++.

Just one more question.  Is the constant restraint just within the body of that function.  ie.  If the pointer is passed to another function, will that function be able to change the pointer's value?

Ged Byrne
Friday, June 04, 2004

Ged,

The constness is "contagious".

If:

int foo(const int* ptr)
{
...
}

ptr, for "foo" is const. So if there's another function named "bar":

int bar(int* lalala)
{
..
}

Foo can't call:

bar(ptr);

Since it's illegal to pass const pointers to functions that expect non-const inputs.

And about your "not to use C++" comment... I just don't want to start a religious war here :-) Each language, IMHO, has its place. This is proved by reality.

Eli Bendersky
Friday, June 04, 2004

"Just one more question.  Is the constant restraint just within the body of that function.  ie.  If the pointer is passed to another function, will that function be able to change the pointer's value?"

myFunc( const int * px ) {
// you are not able to change the value pointed by px, thus
  *px = 30; // is illegal
                  // until const is explicitly overriden by casting
}

myFunc( int * px ) {
// you are allowed to change the value pointed by px
  *px = 30; // is OK
}

Regards,

chance.

chance
Friday, June 04, 2004

Eli,

Thanks for the confirmation.

I don't want to start a religous war either.  The comment was regarding my own shortcomings :)  I envy the people who are able to cope with C++, it is all beyond me.

Ged Byrne
Friday, June 04, 2004

> So let him assign "ptr = 0", what harm does it make ?

It depends entirely on what he does with it afterwards, really, doesn't it. You can check things at compiletime or try and debug them later. Personally I will always try and get a machine to do the work for me so that it catches my mistakes. It is like checking (a == 0) or (0 == a) both are valid, yet the latter will stop you mistyping and ending up with an assignment.


Friday, June 04, 2004

The declaration

int foo (int *const ptr)

imparts to the compiler that the parameter ptr is not to be changed.  There are two benefits to this---one, it's an assumption the programmer is stating and any assignments to ptr is some form of error in the code.  Second, it may allow the compiler to do some optimizations that it might not otherwise be able to do.

Sean Conner
Saturday, June 05, 2004

*  Recent Topics

*  Fog Creek Home