const , and valid converstions of pointers thereto

Discussion in 'C Programming' started by d3x0xr, Nov 30, 2006.

  1. d3x0xr

    d3x0xr Guest

    ---- Section 1 ----

    ------
    x.c

    int main( void )
    {
    char **a;
    char const *const *b;
    b = a; // line(9)
    }
    ------

    wpp386 x.c

    x.c(9): Warning! W1178: Type qualifier mismatch
    x.c(9): Note! N2003: source conversion type is 'char const *const *'
    x.c(9): Note! N2004: target conversion type is 'char **'

    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.


    (const char **) = (char **) does not merit a warning, given that (const
    char *) = (char *) does not.


    -----------------
    Some actual output from compilers - this is the program.

    (Oops, this demonstrates the extra warnings in converting from (char **)
    to (char const * const *)

    ---
    int main( void )
    { char **a; // line (2)
    const char *const* b; // line (3)
    char *xa; // line (4)
    const char *xb; // line (5)
    int *xia; // line (6)
    const int *xib; // line (7)
    b = a; // line (8)
    a = b; // line (9)
    xa=xb; // line (10)
    xb=xa; // line (11)
    xia=xib; // line (12)
    xib=xia; // line (13)
    return 0; // line (14)
    }

    (msvc compiling as C)
    [line](9) : error C2440: '=' : cannot convert from 'const char *const *
    ' to 'char ** '
    Conversion loses qualifiers
    [line](10) : error C2440: '=' : cannot convert from 'const char *' to
    'char *'
    Conversion loses qualifiers
    [line](12) : error C2440: '=' : cannot convert from 'const int *' to
    'int *'
    Conversion loses qualifiers

    (msvc compiling as C++)
    m:\tmp\x.cpp(9) : error C2440: '=' : cannot convert from 'const char
    *const * ' to 'char ** '
    Conversion loses qualifiers
    m:\tmp\x.cpp(10) : error C2440: '=' : cannot convert from 'const char *'
    to 'char *'
    Conversion loses qualifiers
    m:\tmp\x.cpp(12) : error C2440: '=' : cannot convert from 'const int *'
    to 'int *'
    Conversion loses qualifiers

    (gcc compiling as C)
    x.c: In function 'main':
    x.c:8: warning: assignment from incompatible pointer type
    x.c:9: warning: assignment from incompatible pointer type
    x.c:10: warning: assignment discards qualifiers from pointer target
    type
    x.c:12: warning: assignment discards qualifiers from pointer target
    type

    (g++ compiling as c++)
    x.c: In function 'int main()':
    x.c:9: error: invalid conversion from 'const char* const*' to 'char**'
    x.c:10: error: invalid conversion from 'const char*' to 'char*'
    x.c:12: error: invalid conversion from 'const int*' to 'int*'

    (wcc386)
    Open Watcom C32 Optimizing Compiler Version 1.5
    Portions Copyright (c) 1984-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    x.c(8): Warning! W1178: Type qualifier mismatch
    x.c(8): Note! N2003: source conversion type is 'char **'
    x.c(8): Note! N2004: target conversion type is 'char const *const *'
    x.c(9): Warning! W1178: Type qualifier mismatch
    x.c(9): Note! N2003: source conversion type is 'char const *const *'
    x.c(9): Note! N2004: target conversion type is 'char **'
    x.c(10): Warning! W1178: Type qualifier mismatch
    x.c(10): Note! N2003: source conversion type is 'char const *'
    x.c(10): Note! N2004: target conversion type is 'char *'
    x.c(12): Warning! W1178: Type qualifier mismatch
    x.c(12): Note! N2003: source conversion type is 'int const *'
    x.c(12): Note! N2004: target conversion type is 'int *'
    x.c: 15 lines, 4 warnings, 0 errors

    (wpp386)
    M:\tmp>wpp386 x.c
    Open Watcom C++32 Optimizing Compiler Version 1.5
    Portions Copyright (c) 1989-2002 Sybase, Inc. All Rights Reserved.
    Source code is available under the Sybase Open Watcom Public License.
    See http://www.openwatcom.org/ for details.
    x.c(9): Error! E246: col(3) left expression is not a pointer to a
    constant object
    x.c(9): Note! N717: col(3) left operand type is 'char * * (lvalue)'
    x.c(9): Note! N718: col(3) right operand type is 'char const * const *'
    x.c(10): Error! E246: col(3) left expression is not a pointer to a
    constant object
    x.c(10): Note! N717: col(3) left operand type is 'char * (lvalue)'
    x.c(10): Note! N718: col(3) right operand type is 'char const *'
    x.c(12): Error! E246: col(4) left expression is not a pointer to a
    constant object
    x.c(12): Note! N717: col(4) left operand type is 'int * (lvalue)'
    x.c(12): Note! N718: col(4) right operand type is 'int const *'
    x.c: 15 lines, no warnings, 3 errors



    ------

    So in conclusion,

    line 8 is not a warning or error in any C++ compiler.
    nor ls 11 or 13;
    -----------------------------------------------
    ---- section 2 ----
    d3x0xr, Nov 30, 2006
    #1
    1. Advertising

  2. d3x0xr said:

    > ---- Section 1 ----
    >
    > ------
    > x.c
    >
    > int main( void )
    > {
    > char **a;
    > char const *const *b;
    > b = a; // line(9)
    > }


    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. But 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.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Nov 30, 2006
    #2
    1. Advertising

  3. > d3x0xr said:
    >> int main( void )
    >> {
    >> char **a;
    >> char const *const *b;
    >> b = a; // line(9)
    >> }


    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.

    --
    Best regards, _ _
    .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
    ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
    ooo +--<mina86*tlen.pl>---<jid:mina86*chrome.pl>--ooO--(_)--Ooo--
    Michal Nazarewicz, Nov 30, 2006
    #3
  4. Michal Nazarewicz said:

    <snip>
    >
    > If what you are saying [about const] is valid [...]


    ....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.

    CHRIS!

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Nov 30, 2006
    #4
  5. d3x0xr

    d3x0xr Guest

    Richard Heathfield:
    > d3x0xr said:
    >
    >> ---- Section 1 ----
    >>
    >> ------
    >> x.c
    >>
    >> int main( void )
    >> {
    >> char **a;
    >> char const *const *b;
    >> b = a; // line(9)
    >> }

    >
    > 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 */


    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.
    d3x0xr, Nov 30, 2006
    #5
  6. Richard Heathfield <> writes:

    > d3x0xr said:
    >
    >> ---- Section 1 ----
    >>
    >> ------
    >> x.c
    >>
    >> int main( void )
    >> {
    >> char **a;
    >> char const *const *b;
    >> b = a; // line(9)
    >> }

    >
    > 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. But 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.


    This problem comes from two issues interacting:

    1) The standard forbids certain dangerous conversion involving
    qualified types; and
    2) To make things easy the rule forbids some safe conversion like the
    one give.

    The rule in the standard is designed to prevent modification of a
    const like this:

    int main(void)
    {
    const char foo = 'F';
    char *p;
    const char **cp = (const char **)&p; // force with cast
    *cp = &foo;
    *p = 'B';

    printf("c = %c\n", foo);
    return EXIT_SUCCESS;
    }

    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.

    --
    Ben.
    Ben Bacarisse, Nov 30, 2006
    #6
  7. d3x0xr

    d3x0xr Guest

    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".

    Then, coming back to the C compiler, I get assaulted by warnings.

    Ben Bacarisse:
    > Richard Heathfield <> writes:
    >
    >> d3x0xr said:
    >>
    >>> ---- Section 1 ----
    >>>
    >>> ------
    >>> x.c
    >>>
    >>> int main( void )
    >>> {
    >>> char **a;
    >>> char const *const *b;
    >>> b = a; // line(9)
    >>> }

    >>
    >> 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. But 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.

    >
    > This problem comes from two issues interacting:
    >
    > 1) The standard forbids certain dangerous conversion involving
    > qualified types; and
    > 2) To make things easy the rule forbids some safe conversion like the
    > one give.
    >
    > The rule in the standard is designed to prevent modification of a
    > const like this:
    >
    > int main(void)
    > {
    > const char foo = 'F';
    > char *p;
    > const char **cp = (const char **)&p; // force with cast
    > *cp = &foo;
    > *p = 'B';
    >
    > printf("c = %c\n", foo);
    > return EXIT_SUCCESS;
    > }
    >
    > 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.
    >
    > --
    > Ben.
    d3x0xr, Dec 1, 2006
    #7
  8. "d3x0xr" <> writes:

    > Ben Bacarisse:
    >> Richard Heathfield <> writes:
    >>
    >>> d3x0xr said:
    >>>> int main( void )
    >>>> {
    >>>> char **a;
    >>>> char const *const *b;
    >>>> b = a; // line(9)
    >>>> }
    >>>
    >>> 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. But 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.

    >>
    >> This problem comes from two issues interacting:
    >>
    >> 1) The standard forbids certain dangerous conversion involving
    >> qualified types; and
    >> 2) To make things easy the rule forbids some safe conversion like the
    >> one give.
    >>
    >> The rule in the standard is designed to prevent modification of a
    >> const like this:
    >>
    >> int main(void)
    >> {
    >> const char foo = 'F';
    >> char *p;
    >> const char **cp = (const char **)&p; // force with cast
    >> *cp = &foo;
    >> *p = 'B';
    >>
    >> printf("c = %c\n", foo);
    >> return EXIT_SUCCESS;
    >> }
    >>
    >> 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.
    >>

    <snip standards quotes>
    >>
    >> 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.


    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?

    --
    Ben.
    Ben Bacarisse, Dec 2, 2006
    #8
  9. d3x0xr

    d3x0xr Guest

    Again, without typecasting. There's no safe way to write code without
    getting assaulted by warnrings of undefined conditions.

    Why is that? Why MUST I type cast?

    I don't in C++.

    I don't in gcc.



    Ben Bacarisse:
    > Richard Heathfield <> writes:
    >
    >> d3x0xr said:
    >>
    >>> ---- Section 1 ----
    >>>
    >>> ------
    >>> x.c
    >>>
    >>> int main( void )
    >>> {
    >>> char **a;
    >>> char const *const *b;
    >>> b = a; // line(9)
    >>> }

    >>
    >> 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. But 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.

    >
    > This problem comes from two issues interacting:
    >
    > 1) The standard forbids certain dangerous conversion involving
    > qualified types; and
    > 2) To make things easy the rule forbids some safe conversion like the
    > one give.
    >
    > The rule in the standard is designed to prevent modification of a
    > const like this:
    >
    > int main(void)
    > {
    > const char foo = 'F';
    > char *p;
    > const char **cp = (const char **)&p; // force with cast
    > *cp = &foo;
    > *p = 'B';
    >
    > printf("c = %c\n", foo);
    > return EXIT_SUCCESS;
    > }
    >
    > 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.
    >
    > --
    > Ben.
    d3x0xr, Dec 2, 2006
    #9
  10. d3x0xr

    d3x0xr Guest

    And even at that, if I do typecasst, doesn't that defeat the compiler's
    desire to know that a thing is const?




    Ben Bacarisse:
    > Richard Heathfield <> writes:
    >
    >> d3x0xr said:
    >>
    >>> ---- Section 1 ----
    >>>
    >>> ------
    >>> x.c
    >>>
    >>> int main( void )
    >>> {
    >>> char **a;
    >>> char const *const *b;
    >>> b = a; // line(9)
    >>> }

    >>
    >> 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. But 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.

    >
    > This problem comes from two issues interacting:
    >
    > 1) The standard forbids certain dangerous conversion involving
    > qualified types; and
    > 2) To make things easy the rule forbids some safe conversion like the
    > one give.
    >
    > The rule in the standard is designed to prevent modification of a
    > const like this:
    >
    > int main(void)
    > {
    > const char foo = 'F';
    > char *p;
    > const char **cp = (const char **)&p; // force with cast
    > *cp = &foo;
    > *p = 'B';
    >
    > printf("c = %c\n", foo);
    > return EXIT_SUCCESS;
    > }
    >
    > 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.
    >
    > --
    > Ben.
    d3x0xr, Dec 2, 2006
    #10
  11. "d3x0xr" <> writes:
    > Ben Bacarisse:

    <long text snipped>

    > Again, without typecasting. There's no safe way to write code without
    > getting assaulted by warnrings of undefined conditions.
    >
    > Why is that? Why MUST I type cast?


    I may well have missed your point. I am sorry my answer was of no
    help.

    > I don't in C++.


    Different languages have different rules.

    > I don't in gcc.


    If your question is specific to one implementation, then you will get
    better help in a newsgroup dedicated to that implementation.

    Please don't top-post.

    --
    Ben.
    Ben Bacarisse, Dec 3, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    11
    Views:
    1,089
  2. Javier
    Replies:
    2
    Views:
    544
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,093
    Tim Rentsch
    Nov 10, 2008
  4. Replies:
    4
    Views:
    2,617
  5. Vladimir Menshakov
    Replies:
    1
    Views:
    354
Loading...

Share This Page