Subject: Re: iconv(3) prototype
To: None <mouse@Rodents.Montreal.QC.CA>
From: T.SHIOZAKI <tshiozak@netbsd.org>
List: tech-userlevel
Date: 07/28/2004 17:38:12
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
Subject: Re: iconv(3) prototype
Date: Wed, 28 Jul 2004 03:30:24 -0400 (EDT)
Message-ID: <200407280732.DAA27066@Sparkle.Rodents.Montreal.QC.CA>

> > The point of this problem is that the 2nd argument of iconv() is "a
> > pointer of a pointer".  "char *" can be converted to "const char *"
> > explicitly, but "char **" cannot be converted to "const char **"
> > without warning.
> 
> Well, without a cast, yes.  I've never understood why char ** is
> incompatible with const char **....

Briefly, section 6.5.16.1 of ISO C99 means:
  (1) "T" can implicitly be converted to "const T" and
  (2) "T *" can implicitly be converted to "const T *",
  (3) but "T1 *" cannot implicitly be converted to "T2 *".
Here, T, T1 and T2 are types,
and T1 and T2 are different types from each other.
"const char *" is a different type from "char *", thus
converting from "char **" to "const char **" is corresponding to (3).

The point is a sort of the combination problem between different systems.
For example,

System A declares foo() as: void foo(char **);
System B declares foo() as: void foo(const char **);

If we call it as:
  foo((char **)&str);
OK on System A, but NG on System B.

If we call it as:
  foo((const char **)&str);
OK on System B, but NG on System A.

They are inconsistent.


If we wish to call it without warnings, we need to write as:

#if SYSTEM_A
  foo((char **)&str);
#elif SYSTEM_B
  foo((const char **)&str);
#endif

or

(void (*)(char **))foo((char **)&str);

or

(void (*)(const char **))foo((const char **)&str);


--
Takuya SHIOZAKI