I have the following function:
item *already_met_the_number(const item *p, long n)
{
while (p) {
if (p->num == n)
return p;
else
p = p->next;
}
return NULL;
}
I don't want the data structure to be changed in the function. However later I change the returned item.
I get the following warning from gcc
compiler:
warning: return discards ‘const’ qualifier from pointer target type
How should I rewrite my function following good programming practices?
How should I rewrite my function following good programming practices?
By removing the const
.
I don't want the data structure to be changed in the function.
You don't need the compiler's help for that.
Long answer follows.
Let's look at another function for a second, one that returns a pointer to the NUL of a string.
const char *s1b = "abc";
const char *s1e = end_of( s1b );
char s2b[] = "def";
char *s2e = end_of( s2b );
How would we implement this function so that it works with both const
and non-const
data (as shown)?
Well, C doesn't permit that.[1] We've seen the following approximation:
char *end_of( const char *s ) {
while ( *s ) ++s;
return ( char * )s;
}
The above snippet now works. However, our function also silently allows the following:
const char *s3b = "ghi";
char *s3e = end_of( s3b ); // `*s3e` isn't actually modifiable.
Imperfect, but good enough.
But that's not the situation being asked about here.
The concept of a linked list with unmodifiable nodes makes no sense. You require a modifiable pointer since you return a modifiable pointer. So we're talking about temporarily using a const
pointer for non-const
data.
The best practice would be to not lie to the caller about being able to accept a const
pointer.
item *already_met_the_number( item *p, long n ) {
while ( p ) {
if ( p->num == n )
return p;
else
p = p->next;
}
return NULL;
}
But what about using a non-parameter const
variable and casting the result?
item *already_met_the_number( item *p_noconst, long n ) {
const item *p = p_noconst;
while ( p ) {
if ( p->num == n )
return ( item * )p;
else
p = p->next;
}
return NULL;
}
An explicit cast is one of the most dangerous things in C. Especially a pointer cast. It's so easy to get wrong, or to become wrong as code is maintained, and it can be silent as the very point of the cast is to override safety features.
Adding this second variable and a cast simply makes this function more complex and more dangerous. This is a not a good practice, at least not here.
_Generic
.