the const keyword & function arguments in C

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Is it worth declaring function arguments as const when appropriate?

For example, suppose I'm trying to find the maximum value of an array & the indices at which it occurs.. a prototype might look like:
int max(double *array, int length, double *max, int *indices)

array and length will not be changed; is it useful to declare these as const? Would I do it like this:
int max(double const *const array, int const length, double *max, int *indices)

i.e. array is a constant pointer to constant data and length is a constant integer.

Also, if for some reason I wanted length passed by reference, would I write: int const *length? So length is a pointer to constant data. Or should I write int const *const length? i.e. length is a constant pointer to constant data.

-Eric
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
Definitely worth it to mark the referenced data const. e.g. int max(const double *data, ...). (or double const *data, equivalent). It's part of the interface/contract of the function that it doesn't modify the data. I've encountered a lot of code where const wasn't used when it should have been, and so later when I try pass to it a const pointer, the code doesn't compile or generates warnings. Pretty irritating when that happens.

Now whether or not you mark passed-by-value parameters const e.g. int max(..., const int length, ...), is less critical because it's not really part of the interface of the function. To the caller it makes no difference whether the value is modified inside the function or not. This includes the value of the pointer itself e.g. doing something like "int * const data". I certainly never bother with this. Functions are supposed to be short, so you should know easily if a parameter is modified.

 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Originally posted by: dighn
Definitely worth it to mark the referenced data const. e.g. int max(const double *data, ...). (or double const *data, equivalent). It's part of the interface/contract of the function that it doesn't modify the data. I've encountered a lot of code where const wasn't used when it should have been, and so later when I try pass to it a const pointer, the code doesn't compile or generates warnings. Pretty irritating when that happens.

Now whether or not you mark passed-by-value parameters const e.g. int max(..., const int length, ...), is less critical because it's not really part of the interface of the function. To the caller it makes no difference whether the value is modified inside the function or not. This includes the value of the pointer itself e.g. doing something like "int * const data". I certainly never bother with this. Functions are supposed to be short, so you should know easily if a parameter is modified.

Do you know if using const correctly affords any performance benefits (or performance hits for not using it)?

Also, why would I do double const *data vs double const *const data? (pointer to const data vs const pointer to const data) Is the first option basically irrelevant b/c the pointer is passed by value? (i.e. if I make the input pointer *data point to something else, it only affects the local function).

TehJustinator: I'm in C, so int& length isn't supported. Beyond that, I prefer using int* length so that it's always explicitly clear that I'm holding onto a pointer. i.e. I feel like (although more cumbersome), (*length) += 3 makes it obvious that I'm de-referencing.

Also, using pass by reference for an integer is useful for interfacing to Fortran b/c everything is pass-by-ref in fortran. But yes other than that I don't think you'd ever need to pass input-only variables by reference.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
There are extremely aggressive compiler techniques that can improve performance from judicious and appropriate use of const-ness (e.g. semi-speculative parallelism), though I don't think any commodity compilers use optimizations of that nature.

However, beware the use of const -- more than once I've encountered the case named by dighn (a procedure I would like to call doesn't use const-ness, and all I have is a const-pointer), but I've also seen the other side of that coin on several occasions -- re-working a deeply nested procedure that all of a sudden would like to change a parameter that is passed by reference (but is declared const). Both cases result in pretty unpleasant rewrites of function hierarchies. So the most important thing to keep in mind about const-ness is at design-time: decide what should be const, not what happens to be const.
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Originally posted by: degibson
There are extremely aggressive compiler techniques that can improve performance from judicious and appropriate use of const-ness (e.g. semi-speculative parallelism), though I don't think any commodity compilers use optimizations of that nature.

However, beware the use of const -- more than once I've encountered the case named by dighn (a procedure I would like to call doesn't use const-ness, and all I have is a const-pointer), but I've also seen the other side of that coin on several occasions -- re-working a deeply nested procedure that all of a sudden would like to change a parameter that is passed by reference (but is declared const). Both cases result in pretty unpleasant rewrites of function hierarchies. So the most important thing to keep in mind about const-ness is at design-time: decide what should be const, not what happens to be const.

Oh ok, so it seems like the main benefit is clarity?

I was only planning on making logical things constant. Like the length of an input array in a sort, or the head-node of a tree in insertion.
 

Ken g6

Programming Moderator, Elite Member
Moderator
Dec 11, 1999
16,703
4,661
75
The main benefit is, if you pass in something by reference, but want the data not to be changed by the function, if you (or someone else editing your code later) try to change that data, the compiler will tell you something's wrong. It makes the compiler enforce a little bit of a function contract, if you think in those terms.
 

dighn

Lifer
Aug 12, 2001
22,820
4
81
Originally posted by: eLiu
Do you know if using const correctly affords any performance benefits (or performance hits for not using it)?

Like degibson said, there are possibly performance benefits, but that's not the main reason. The main reason, at least imho, is the expression and enforcement of function contract which can be very helpful in larger code bases.

Also, why would I do double const *data vs double const *const data? (pointer to const data vs const pointer to const data) Is the first option basically irrelevant b/c the pointer is passed by value? (i.e. if I make the input pointer *data point to something else, it only affects the local function).

Yep. Changing what the pointer points to affects the function only since the pointer itself is passed by value.
 
Sep 29, 2004
18,656
68
91
const?

I rarely use it. It is admittadly a safe practice but if you need these kind of checks, you are doing something wrong.

Regarding pointers. With modern processing power, I don't use pointers much. I avoid them a much as possible. I would rather do a deep copy. Only optimize as needed for the target environment. And in industry, about a year ago I ran into one hell of a shit box of software that used pointers way to much. The whole application was a hack and we basically took the work away from the subcontractor because they were Fing everything up.
 

eLiu

Diamond Member
Jun 4, 2001
6,407
1
0
Originally posted by: IHateMyJob2004
const?

I rarely use it. It is admittadly a safe practice but if you need these kind of checks, you are doing something wrong.

Regarding pointers. With modern processing power, I don't use pointers much. I avoid them a much as possible. I would rather do a deep copy. Only optimize as needed for the target environment. And in industry, about a year ago I ran into one hell of a shit box of software that used pointers way to much. The whole application was a hack and we basically took the work away from the subcontractor because they were Fing everything up.

Uhm... when the data is several GB, deep copy is not an option. Even if I can operate on it a few MB at a time, it's still a waste to copy needlessly.
 
Sep 29, 2004
18,656
68
91
Originally posted by: eLiu
Originally posted by: IHateMyJob2004
const?

I rarely use it. It is admittadly a safe practice but if you need these kind of checks, you are doing something wrong.

Regarding pointers. With modern processing power, I don't use pointers much. I avoid them a much as possible. I would rather do a deep copy. Only optimize as needed for the target environment. And in industry, about a year ago I ran into one hell of a shit box of software that used pointers way to much. The whole application was a hack and we basically took the work away from the subcontractor because they were Fing everything up.

Uhm... when the data is several GB, deep copy is not an option. Even if I can operate on it a few MB at a time, it's still a waste to copy needlessly.

Like I said, unless there are performance related issues it is bad practice.

And memcopy is a cheap(fast) operation.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: IHateMyJob2004
Originally posted by: eLiu
Originally posted by: IHateMyJob2004
const?

I rarely use it. It is admittadly a safe practice but if you need these kind of checks, you are doing something wrong.

Regarding pointers. With modern processing power, I don't use pointers much. I avoid them a much as possible. I would rather do a deep copy. Only optimize as needed for the target environment. And in industry, about a year ago I ran into one hell of a shit box of software that used pointers way to much. The whole application was a hack and we basically took the work away from the subcontractor because they were Fing everything up.

Uhm... when the data is several GB, deep copy is not an option. Even if I can operate on it a few MB at a time, it's still a waste to copy needlessly.

Like I said, unless there are performance related issues it is bad practice.

And memcopy is a cheap(fast) operation.

I agree with IHateMyJob2004, to some extent. Specifically, my thoughts are:
* Pass-by-reference is, in many but not all cases, merely a performance optimization.
* In code that is written entirely by one person (or by a very small group that never changes), there's little benefit to religious use of const, if that is the preference of the coder(s). (though I, myself, use it often)
* I think that most code can/should be written in languages higher than C/C++, essentially above the level of abstraction of a pointer anyway

And one last bullet point that doesn't agree:
* Any code that is written in C/C++ should automatically be considered high performance code. After all, for what purpose was the language chosen? Hence, pervasive use of pass-by-reference (pointer) is justified. The 'memcpy is cheap' argument leads to bloat, and used throughout a codebase, it is a prime example of what not to do, now that frequency scaling is hitting the wall, especially when 'const' can save the day and elide the copy altogether for read-only parameters.
 
Sep 29, 2004
18,656
68
91
degibson,

For military systems, you won't be allowed to use much other than Ada or C/C++ for anything that acts as a controller, regardless of performance needs. The project I am on right now will probably use 2% of the CPU and that is with no tweaks. These days, you can use Java for GUIs though which is VERY nice.

One other thing. memcpy is cheap but it might lead to fragmentation related issues. Thus a risk. I guess what i hsould have said is that if you are passing around very large objects, maybe a singleton would be the better solution. Depends on the specific scenario I guess.
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: IHateMyJob2004
For military systems, you won't be allowed to use much other than Ada or C/C++ for anything that acts as a controller, regardless of performance needs. The project I am on right now will probably use 2% of the CPU and that is with no tweaks. These days, you can use Java for GUIs though which is VERY nice.

What is the military's decision process behind Ada/C/C++? I assume we're not talking about control systems for aircraft and the like (though those are definitely low-level). Is it safe to assume that the military is just being its usual behind-the-times, conservative, paranoid, and inefficient self? Especially for batch jobs, it seems like a nice high-productivity language would suit better for many mission-non-critical applications (please excuse the pun -- I could not resist).

In general, I suppose I should have prefixed my post above with "On commodity platforms..." Your post reminded me of the embedded community, which is very often extremely low performance (in absolute terms of course), but utterly requires C (or maybe C++) because of limitations in the software stack.

One other thing. memcpy is cheap but it might lead to fragmentation related issues. Thus a risk. I guess what i hsould have said is that if you are passing around very large objects, maybe a singleton would be the better solution. Depends on the specific scenario I guess.

There is also the concern of running out of stack. Many environments are stack-constrained, the default stack size isn't always enough for a big application.

Another point, about copying objects around: As you know, passing objects is quite complicated when those objects aren't just collections of primitive types. For instance, in large projects written by real design-pattern fanatics, objects come from object factories (and may be specially decorated by factories). Making new 'bootleg' objects fly through the stack breaks the pattern.

 

Markbnj

Elite Member <br>Moderator Emeritus
Moderator
Sep 16, 2005
15,682
14
81
www.markbetz.net
What is the military's decision process behind Ada/C/C++? I assume we're not talking about control systems for aircraft and the like (though those are definitely low-level). Is it safe to assume that the military is just being its usual behind-the-times, conservative, paranoid, and inefficient self?

Pretty much, yes :). They designed and bankrolled ADA, which is why it is one of their standard tools. Otherwise, the list of what tools are allowed in milspec work is pretty tightly defined.
 

bsobel

Moderator Emeritus<br>Elite Member
Dec 9, 2001
13,346
0
0
I rarely use it. It is admittadly a safe practice but if you need these kind of checks, you are doing something wrong.

No, actually your not...
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Originally posted by: Markbnj
Pretty much, yes :). They designed and bankrolled ADA, which is why it is one of their standard tools. Otherwise, the list of what tools are allowed in milspec work is pretty tightly defined.

Have you ever heard the story about why US railroad tracks are 4 ft 8.5 inches in gauge? (this answer is actually fiction, but its interesting)

- US railroads were modeled after those in England (4 ft 8.5 in)
- English railroads used the same gauge as tramways (4 ft 8.5 in)
- English tramways were built using the same tools as those used by wagon builders, and English wagon wheels were gauged to 4 ft 8.5 in
- English wagons were gauged to match the wagon ruts that already criss-crossed the island (4 ft 8.5 in apart)
- Those ruts were made by Roman chariots (4 ft 8.5 in gauge)

The moral of the story is: military specs last forever.

Bonus extra:
I seem to also recall a story about some monkeys, a bunch of bananas, and a firehose that also seems to apply to this thread.