C99 const keyword - indirection

Started by
19 comments, last by phresnel 14 years, 11 months ago
I did quick googling on this but the explanations found are too simple (eg. "a const object is unmodifiable"). Ok, say I have a struct and two functions like this:
typedef struct
{
   otherstruct_t* ptr;
} somestruct_t;

void do_something(const somestruct_t* s)
{
   s->ptr->... = ...;
}

somestruct_t* return_something(const somestruct_t* array, int index)
{
   return &array[index];
}





What gives in these cases? I thought that const implies I can't write directly in the type qualified (not counting indirection) in the scope of the function, but I get GCC warning me about constness getting discarded by functions similar to the two above. I've probably misunderstood the keyword. I'm not completely inexperienced with C but I didn't bother with this qualifier before, this time however I'd like to help the compiler's optimizer unless it gives me too much of a headache.
Advertisement
Above code is not compilable, and I can't really imagine what you mean exactly; please post real code, not pseudo code.

Wikipedia has a nice page about const correctness, as well as the C++ FAQ Lite.
It's pseudo in that I have not written out a definition for otherstruct_t, which is another structure. Nor have I written out the assignment. But it shouldn't matter for the understanding of the problem.

Don't know if reading about C++ constness will help, considering there are differences in how C deals with constants compared to C++.

Will check out wiki, thanks.
Just checked some code that I think you really mean (C++ though):

struct somestruct_t{   somestruct_t* ptr;};somestruct_t* return_something(const somestruct_t* array, int index){   return array + index;}


This won't compile, because gcc spits an error for trying to implicitly discard the const qualifier.
Quote:Original post by Beyond_Repair
It's pseudo in that I have not written out a definition for otherstruct_t, which is another structure. Nor have I written out the assignment. But it shouldn't matter for the understanding of the problem.


It matters, because

somestruct_t* return_something(const somestruct_t* array, int index){   return array[index];}


is invalid code. Function return_something accepts a const somestruct_t* as a parameter, and by signature returns a somestruct_t*; but actually your return statement tries to return a somestruct_t, i.e. invalid code.
It does compile, but I'm allowing warnings (not like it matters as I always fix them and never lead them to be, like in this case). :P

Edit: Uggh, I forgot the address of operator in my example. Sorry-.
About const correctness:

* C++ FAQ Lite, [18]
* Wikipedia: Const Correctness
Quote:Original post by Beyond_Repair
It does compile, but I'm allowing warnings (not like it matters as I always fix them and never lead them to be, like in this case). :P


Okay, now I am really in C. Let me dig ...
Aha, Wikipedia probably answers my question:

Quote:Another loophole applies both to C and C++. Specifically, the languages dictate that member pointers and references are "shallow" with respect to the const-ness of their owners — that is, a containing object that is const has all const members except that member pointees (and referees) are still mutable.


Weird GCC is giving me a warning then, but I guess it's because it's not "recommended".
Quote:Original post by Beyond_Repair
Aha, Wikipedia probably answers my question:

Quote:Another loophole applies both to C and C++. Specifically, the languages dictate that member pointers and references are "shallow" with respect to the const-ness of their owners — that is, a containing object that is const has all const members except that member pointees (and referees) are still mutable.


Weird GCC is giving me a warning then, but I guess it's because it's not "recommended".

What is the warning and what gcc version?
The following produces no warnings using:
$ gcc -ansi -pedantic -Wall -Wextra const_aware.c
#include <malloc.h>typedef struct{   int i;} otherstruct_t;typedef struct{   otherstruct_t* ptr;} somestruct_t;void do_something(const somestruct_t* s){   s->ptr->i = 2;}const somestruct_t* return_something(const somestruct_t* array, int index){   return array + index;}int main(){	somestruct_t* s = malloc(sizeof(somestruct_t));	s->ptr = malloc(sizeof(otherstruct_t));	s->ptr->i = 1;	do_something(s);	free(s->ptr);	free(s);		return 0;}

This topic is closed to new replies.

Advertisement