Date: Mon, 29 May 2006 21:09:55 +1000 (EST) From: Bruce Evans <bde@zeta.org.au> To: Yar Tikhiy <yar@comp.chem.msu.su> Cc: freebsd-arch@freebsd.org Subject: Re: Can fts_open() be constified further? Message-ID: <20060529200215.T24032@delplex.bde.org> In-Reply-To: <20060528164328.GA84031@comp.chem.msu.su> References: <20060528164328.GA84031@comp.chem.msu.su>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 28 May 2006, Yar Tikhiy wrote: > Currently, fts_open() is declared as follows: > > FTS * > fts_open(char * const *path_argv, int options, > int (*compar)(const FTSENT * const *, const FTSENT * const *)); > > This means that one cannot pass pointers to constant strings in > path_argv[] without getting rather justified warnings from cc. > AFAIK, fts(3) functions aren't supposed to modify the path strings. > Hence the prototype asks to be changed slightly: > > fts_open(const char * const *path_argv, int options, > ^^^^^ > This shouldn't break fts consumers because a pointer to a variable > can be converted to a pointer to a constant w/o warnings (but not > the other way around.) Can anybody see other possible side effects > from such change? It wouldn't work, for the same reasons that it doesn't work for execve(): plain "char **" cannot be converted to "const char * const *". Only "const char **" and of course itself can be converted. "char * const *" cannot be converted but is weird compared with "char **". All this follows from the type rule that you expressed informally. "const" can only be added at the outer level when the inner types are the same. Set T1 = "char *" and T2 = "const char *" to reduce confusion about the levels. Then: char ** = pointer to T1 = PT1 char * const * = const pointer to T1 = CPT1 const char ** = pointer to T2 = PT2 const char * const * = const pointer to T2 = CPT2 PT1 can be converted to CPT1 and PT2 can be converted to CPT2. No other conversions from adding a "const" are permitted, since T1 != T2. The prototypes for the execve() family and presumably for fts_open() are chosen so that the most important non-constified type (PT1) can be converted to the type in the prototype (CPT1). PT1 cannot be converted to CPT2 since "const" is not very well designed. Allowing this conversion without redesigning "const" would make "const" even less well designed. From the draft C standard (n869.txt): %%% [#6] EXAMPLE 3 Consider the fragment: const char **cpp; char *p; const char c = 'A'; cpp = &p; // constraint violation *cpp = &c; // valid *p = 0; // valid The first assignment is unsafe because it would allow the following valid code to attempt to change the value of the const object c. %%% It looks harmless to add a "const" to the inner type in &p, but this example shows that it unsafe. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20060529200215.T24032>