This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: ... discard qualifiers ...




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.




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]