This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: ... discard qualifiers ...
- To: Davide Libenzi <dlibenzi at maticad dot it>
- Subject: Re: ... discard qualifiers ...
- From: llewelly at 198 dot dsl dot xmission dot com
- Date: Sun, 2 Jan 2000 16:49:28 -0700 (MST)
- cc: gcc at gcc dot gnu dot org
On Sun, 2 Jan 2000, Davide Libenzi wrote:
> On Sun, 02 Jan 2000, llewelly@198.dsl.xmission.com wrote:
> > On Sun, 2 Jan 2000, Davide Libenzi wrote:
> >
> > >
> > > Hi guys,
> > >
> > > is there a way other than '-fwritable-strings' to avoid errors in this case :
> > >
> > > void foo(const void * p)
> > > {
> > > ...
> > > }
> > >
> > > main()
> > > {
> > >
> > > foo( "Hello world !" );
> > >
> > > }
> > >
> > gcc 2.95.2 does not generate any errors for the above code (once the '...'
> > is commented out); in both C and C++, 'char const*' (the type of a
> > string literal) can be implicitly converted to 'void const*' (foo's
> > parameter type).
> >
> > I don't know what -fwritable-strings has to do with any of this.
> >
> > Perhaps you need to re-phrase your question.
>
> Ops ...
>
> I've translated a step ahead the code. This is the real one :
>
> typedef void * Pointer;
>
> void foo(const Pointer p)
> {
> ...
> }
>
> void main()
> {
> foo( "Hello World !" );
> }
>
The solution: declare foo() as:
foo(void const* p)
//
and abandon the typedef.
The explanation:
If I comment out the '...'
I get:
$gcc -g -Wall char_const_p_to_void_const_p.cc
char_const_p_to_void_const_p.cc:9: return type for `main' changed to `int'
char_const_p_to_void_const_p.cc: In function `int main(...)':
char_const_p_to_void_const_p.cc:10: passing `const char *' as argument 1
of `foo(void *)' discards qualifiers
From this error message, it is clear that
typedef void * Pointer;
void foo(const Pointer p)
//...
is translated to:
void foo(void * const p)
//..
which is indistinquishable from:
void foo(void* p)
//..
which not the same as:
void foo(const void* p)
//..
(from your earlier message.)
Why?
If you are not familiar with the difference between 'const void*',
'void const*'and 'void*const' see
http://www.cerfnet.com/~mpcline/c++-faq-lite/const-correctness.html
(If you are learning C, and not C++, the const issues are similar, but
I don't know where to tell you where to look.)
'typedef void * Pointer' creates an alias for the type 'void*'. In a
sense, the 'void' and the '*' are globbed together; any type
qualifiers applied to 'Pointer' apply to 'void*', which is a pointer
type. So in 'const Pointer' the 'const' applies to the pointer, *not* to
the object pointed at. Thus, 'const Pointer' ==> 'void* const' ==>
'(void*) const' (The parantheses are incorrect syntax; they are
intended only for clarification.).
'foo(void*const p)' declares a function that promises not to chage the
value of the pointer it is passed. It can do whatever it wants to any
objects the pointer points *at*, but it can't change the pointer itself.
So given:
void foo(void*const p);
int main()
{
void* c;
//...
foo(c);
}
you are garunteed (by foo()'s declaration) that foo will not change the
value of 'c'. It might change what c points to, but not c itself.
However, C and C++ pass parameters by value; parameters are copied from
the caller to the callee. So foo()'s promise that it won't change 'c' is
meaningless; foo() couldn't change 'c' if it wanted to. So
'foo(void*const p)' is equivalent to 'foo(void* p)'.
In your example, the call 'foo("Hello World!")' is passing a char const*
to foo(). (The type of a string literal is char const* .), so you get an
error.