Okay this is the error, when I went through and cleaned up all the
warnings of passing (char **) as (const char **) parameters in other
compilers (gcc, MSVC), by converting function parameters to (char const
*const *), I STILL had warnings in watcom. This warning should please
to go away[engrish].

(though I still think that if the context is variable data passed to a
process expecting constant data, even if not all levels of indirection
are constant, it should be a compatible conversion, but am proven wrong
by C++ compilers)

----
Cut - ignore after this point.

Please do flog me if I dare misspell or mispunctuate.

In the beginning there is char, which is synonymous for purposes of this
conversation as byte, the plural of which is bytes.

All plural references may be assumed as preferably at least one, but
often more than one.

char c;

c is a variable character.

char const cc;
-or- const char cc;

c is a constant character.

char *s;

a variable pointer which points to a variable character;

char const *s;
-or- const char *s;

a variable pointer which points to a constant character.

char * const s;

A constant pointer which points to a variable character.

char const * const s;
-or- const char * const s;

a constant pointer which points to a constant character;

char * * l;

a variable pointer which points to a variable pointer which points to a
variable character.

char const * * l;
-or- const char * *l;

a variable pointer which points to a variable pointer which points to a
constant character.

char * const * l;

a variable pointer which points to a constant pointer which points to a
variable character;

char * * const l;

a constant pointer which points to a variable pointer which points to a
variable character;

char const * const * s;
-or- const char * const * s;

a variable pointer which points to a constant pointer which points to a
constant character.

char const * * const s;
-or- const char * * const s;

a constant pointer which points to a variable pointer which points to a
constant character.

char const * const * const s;
-or- const char * const * const s;

a constant pointer which points to a constant pointer which points to a
constant character.

One may assume that any code which requires a constant character may be
passed a variable character, with consideration that the implementation
is a single thread, and that the user of the constant data will
compelete before the data will be changed.

A more modern compiler might offer an option of declaring a variable
with volatile characteristics, such that the variable is assumed to be
able to change before a given process completes.

Most all modern compilers, and probably even lint processesors provide
no warning for converting a (char *) to a (const char *), that is if you
will recall, treating a variable character as a constant, immutable
character. Providing, even enforcing, that the process operating on the
data will not modify the data itself.

passing any such reference of non constant data to a constant data
process should not require a warning.

Advertisements

Richard Heathfield <> writes:
> Consider:
>
> char foo = 'F';
> char bar = 'B';
> char *baz = &foo;
> char **quux = &baz;
> char const * const * eric;
>
> eric = quux; /* erroneous, and equivalent to your code */
>
> The compiler ought to be able to know for sure, because eric is a
> pointer to a const pointer to char, that *eric will not change.
> because you can do this at any time:
>
> *quux = &bar;
>
> it becomes possible for legal code to subvert the constness of
> *eric, and the compiler won't like that even a little bit.

As far as I know, the only thing const means is that you (the
programmer) cannot change constant of *eric using pointer eric (since
*eric is of type const char *const; same goes for **eric). Compiler
does not care or know if the actual value can change.

If what you are saying is valid then the following would be invalid:

#v+
char foo[] = "foo";
const char *bar = foo;
#v-

because (as you put it) the compiler ought to be known for sure that
*bar will never change but indeed it can through *foo.

....then I'm a Dutchman. My apologies to the OP. I shouldn't have answered
that question at all. A few years ago, I worked out the logic behind the
necessity for the C Standard to be so bitchy about constness (because
somebody at work happened to ask me a very similar question to the OP's,
and it mattered, and so I looked very closely at it), and I guess I
believed, very late last night, that I still remembered it clearly enough
to explain it. Apparently not.

Why would this not be legal, you're just adding restriction on what you
will do via eric...
>
> The compiler ought to be able to know for sure, because eric is a
pointer to
> a const pointer to char, that *eric will not change. But because you
can do
> this at any time:
>
> *quux = &bar;

however, the standard provides for declarations that are
const volatile int blah;

which means it will change, but it will not be changed by the variable
blah.

Again, what they tell me I have a bad interpeation of is that the const
makes it so that the data will definitly be ROM type data and not
writable, it is not such, it does mean that via the reference of
varaible XXXXX it will not be changed, it does not state that beyond the
context of XXXXX that the variable will not change.
>
> it becomes possible for legal code to subvert the constness of *eric,
and
> the compiler won't like that even a little bit.
>
> --
> Richard Heathfield
> "Usenet is a strange place" - dmr 29/7/1999
> http://www.cpax.org.uk
> email: rjh at the above domain, - www.

Note that the compiler wants to be able to assume the foo can't change
(and maybe more importantly the programmer wants to assume that!) but
if it allowed the assignment I forced with the cast, the const foo can
be changed, silently.

To keep things simple, the standard says:

6.3.2.3:

[2] For any qualifier q, a pointer to a non-q-qualified type may be
converted to a pointer to the q-qualified version of the type; the
values stored in the original and converted pointers shall compare
equal.

and then:

6.7.3 Type qualifiers

[9] For two qualified types to be compatible, both shall have the
identically qualified version of a compatible type; the order of
type qualifiers within a list of specifiers or qualifiers does not
affect the specified type.

which, I think, allows common (safe) usages, forbids dangerous usages
as above but also rules out certain safe combinations involving more
than one level of indirection.

my point isn't even in typecasting, no typecast operator considered, as
typecasting allows the programmer to break all rules without warning or
error.

The case is, if i start writing routines that accept const char *...

then I can definatly safely pass "blah" to it, as a const char *.

if the routine is written to take a 'char*' then there are warnings
given when converting from the const char * to the char *.

So, I modify the routines to take const char *... but then eventually I
end up with a routine that takes the address of one of these
parameters... either as a char const *const * or a char const **, both
appropriate to taking the address of a const char * to pass to the
routine.

The deeper one goes with making code correct and declaring const char *
where the code definatly does not modify the content of the string, the
more trouble one has. If I had left everything as 'char*' and left the
const off, I would not be having this discussion...

Actually, the point that started this was taking all this wonderful C
code and compiling it wilth a C++ compiler which definately FORBIDS char
* = const char *. So, the parameters had to change to have a const
modifier where const data was passed such as "xyzzy".

I know, but I put the cast in because it is needed. I then tried to
show why the cast helps. It reminds you that what some seemingly safe
assignments are not because they would allow a const object to be
changed. I know that in your original example, this is not the case,
but the standard has opted for a simple rule that also rules out some
safe combinations.

Does anyone know how compatibility between pointers to qualified types
could have been worded to allow all safe combinations whilst ruling
out all unsafe ones?
> The case is, if i start writing routines that accept const char *...
>
> then I can definatly safely pass "blah" to it, as a const char *.
>
> if the routine is written to take a 'char*' then there are warnings
> given when converting from the const char * to the char *.
>
> So, I modify the routines to take const char *... but then eventually I
> end up with a routine that takes the address of one of these
> parameters... either as a char const *const * or a char const **, both
> appropriate to taking the address of a const char * to pass to the
> routine.

But one of these (char const **) *must* be outlawed (or forced with a
cast) because it allows a const object to be modified. The other is
just caught in the net.
> The deeper one goes with making code correct and declaring const char *
> where the code definatly does not modify the content of the string, the
> more trouble one has. If I had left everything as 'char*' and left the
> const off, I would not be having this discussion...

But then you get no const-safety. At least this way you have to stop
and think: to pass this value here I need a cast -- is it really a
safe thing to do?

Share This Page

Welcome to The Coding Forums!

Welcome to the Coding Forums, the place to chat about anything related to programming and coding languages.

Please join our friendly community by clicking the button below - it only takes a few seconds and is totally free. You'll be able to ask questions about coding or chat with the community and help others.
Sign up now!