casting const away

Discussion in 'C Programming' started by copx, Jan 6, 2011.

  1. copx

    copx Guest

    In a situation like this

    void my_func(const FOO_T *);

    *foo = 'b';
    my_func(foo);
    putchar(*foo);

    Is the compiler allowed to replace the second foo->a with 'b'
    i.e. allowed to assume that my_func does indeed not modify
    foo? I mean in C you one cast "const" away within said function.
    I wrote a test program who did just that, compiled with GCC
    -Wall -Wextra -ansi -pedantic -O3 : not even a warning and
    the compiler did not optimize the dereference away..
    copx, Jan 6, 2011
    #1
    1. Advertising

  2. copx

    copx Guest

    "copx" wrote in message news:ig3l22$3hb$...
    >[snip]
    >Is the compiler allowed to replace the second foo->a with 'b'
    >i.e. allowed to assume that my_func does indeed not modify
    >foo? I mean in C you one cast "const" away within said function.
    >I wrote a test program who did just that, compiled with GCC
    >-Wall -Wextra -ansi -pedantic -O3 : not even a warning and
    >the compiler did not optimize the dereference away..


    Wow, clc isn't what it used to be. In the good ol' days these
    group was so full of people who had memorized the C standard
    like Grand Ayatollahs the Quran that such a simple standard
    question was usually answered within minutes.

    Whatever, so I grabbed a draft copy of the standard and
    tried to figure it out myself. These documents really aren't
    written with end-users in mind, I tell you. However, after
    10 minutes or so I arrived at the conclusion that this works
    and is guranteed to work because "const" is only really
    meaningful when it's applied to the "object" itself. I.e. a const
    pointer to something doesn't actually tell the compiler
    that the object pointed to is constant, this type of "constness"
    only exist to produce compiler warnings which may aid
    the programmer. By expliticly casting to a non-const
    pointer I get no warning because removing the "const" from
    the pointer just means.. telling the compiler not to
    produce a warning!
    copx, Jan 6, 2011
    #2
    1. Advertising

  3. copx

    Ian Collins Guest

    On 01/ 6/11 06:47 PM, copx wrote:
    > In a situation like this
    >
    > void my_func(const FOO_T *);
    >
    > *foo = 'b';
    > my_func(foo);
    > putchar(*foo);
    >
    > Is the compiler allowed to replace the second foo->a with 'b'


    What second foo->a? You haven't shown a first, let alone a second.
    Without code your post does not make sense.

    --
    Ian Collins
    Ian Collins, Jan 6, 2011
    #3
  4. copx

    copx Guest

    "Ian Collins" wrote in message news:...

    On 01/ 6/11 06:47 PM, copx wrote:
    >> In a situation like this
    >>
    >> void my_func(const FOO_T *);
    >>
    >> *foo = 'b';
    >> my_func(foo);
    >> putchar(*foo);
    >>
    >> Is the compiler allowed to replace the second foo->a with 'b'

    >
    >What second foo->a? You haven't shown a first, let alone a second.
    >Without code your post does not make sense.


    Oops, I simplified the code after writing the text below and forgot
    to update the text to reflect the change. "Second foo->a" should
    "Second *foo".





    --
    Ian Collins
    copx, Jan 6, 2011
    #4
  5. copx

    copx Guest

    "copx" wrote in message news:ig3l22$3hb$...
    Here's some compile-ready code which illustrates the issue:

    #include <stdio.h>

    void foo(const int *c)
    {
    *((int *)c) = 'B';
    }


    int main(void)
    {
    int a = 'A';

    foo(&a);

    putchar(a);

    return 0;
    }


    ====
    Result: no warnings, prints 'B';

    As I wrote in the other post I think I have figured it out
    already.
    copx, Jan 6, 2011
    #5
  6. copx

    Ike Naar Guest

    On 2011-01-06, copx <> wrote:
    > In a situation like this
    >
    > void my_func(const FOO_T *);
    >
    > *foo = 'b';
    > my_func(foo);
    > putchar(*foo);
    >
    > Is the compiler allowed to replace the second foo->a with 'b'
    > i.e. allowed to assume that my_func does indeed not modify
    > foo? I mean in C you one cast "const" away within said function.
    > I wrote a test program who did just that, compiled with GCC
    > -Wall -Wextra -ansi -pedantic -O3 : not even a warning and
    > the compiler did not optimize the dereference away..


    The code has undefined behaviour.

    6.7.3
    5 If an attempt is made to modify an object defined with a
    const-qualified type through use of an lvalue with non-const-qualified
    type, the behavior is undefined.

    The compiler is not obliged to give a warning for undefined behaviour.
    Ike Naar, Jan 6, 2011
    #6
  7. copx

    Guest

    copx <> wrote:
    >
    > Here's some compile-ready code which illustrates the issue:
    >
    > #include <stdio.h>
    >
    > void foo(const int *c)
    > {
    > *((int *)c) = 'B';
    > }
    >
    >
    > int main(void)
    > {
    > int a = 'A';
    >
    > foo(&a);
    > putchar(a);
    > return 0;
    > }
    >
    > ====
    > Result: no warnings, prints 'B';


    It might just as well have printed 'A'. You have lied to the compiler
    by declaring that foo() does not modify what its argument points to but
    going ahead and doing so anyway. The compiler is permitted to believe
    the declaration but is not required to, so either result is acceptable.
    The code is not strictly conforming, but does not violate any
    constraints so no diagnostics are required. It also does not contain
    undefined behavior, just unspecified behavior.
    --
    Larry Jones

    I keep forgetting that rules are only for little nice people. -- Calvin
    , Jan 6, 2011
    #7
  8. copx

    copx Guest

    "Ike Naar" wrote in message
    news:...
    >The code has undefined behaviour.
    >
    >6.7.3
    >5 If an attempt is made to modify an object defined with a
    >const-qualified type through use of an lvalue with non-const-qualified
    >type, the behavior is undefined.


    I read the same section of the standard and this doesn't support
    your statement IMO. The standard talks about OBJECTS with
    a const-qualified type NOT about const-qualified references to
    non-const-qualified objects. I.e. this only means that modifying a
    "const int" is undefined, const-qualified references to
    non-const-qualified objects aren't mentioned here.

    Digging further I could only find this:
    ==
    const int *ptr_to_constant;
    ...
    The contents of anyobject pointed to by ptr_to_constant shall
    not be modiï¬ed through that pointer,
    ==

    Then I had to reference an entirely different section of the
    standard to figure out the technical definition of "shall not".
    =====
    If a ‘‘shall’’or‘‘shall not’’requirement that appears outside of
    a constraint is violated, the behavior is undeï¬ned.
    ===

    Ok,case finally solved, right? Unfortunately, no!

    The standard only says "through that pointer" notice the "that".
    I can copy the value of the const pointer to a non-const pointer
    and then use this newly created pointer to modify the object thus
    the object is never actually modified "through that pointer".

    The exact, literal meaning of what the standard says validates the
    behavior of GCC IMO, but the wording of the standard is so horribly
    confusing here that I wouldn't be surprised if other compilers interpret
    this mess in a different way.
    copx, Jan 6, 2011
    #8
  9. copx

    Ian Collins Guest

    On 01/ 7/11 10:43 AM, copx wrote:
    >
    > The standard only says "through that pointer" notice the "that".
    > I can copy the value of the const pointer to a non-const pointer
    > and then use this newly created pointer to modify the object thus
    > the object is never actually modified "through that pointer".


    Yes you can, but you have to lie to the compiler (cast) to do so.

    > The exact, literal meaning of what the standard says validates the
    > behavior of GCC IMO, but the wording of the standard is so horribly
    > confusing here that I wouldn't be surprised if other compilers interpret
    > this mess in a different way.


    The wording is clear: once you lie to the compiler you are in the land
    of undefined behaviour.

    --
    Ian Collins
    Ian Collins, Jan 6, 2011
    #9
  10. copx

    sandeep Guest

    christian.bau writes:
    > Use "const int* restrict" instead:
    >
    > int i; const int* restrict p = &i; * (int *) p = 1; // Undefined
    > behaviour


    I don't believe that this will be an undefined behavior because p and
    (int*)p are both pointers to the same memory address hence there is no
    aliasing here.
    sandeep, Jan 6, 2011
    #10
  11. copx

    copx Guest

    "Ian Collins" wrote in message news:...
    >Yes you can, but you have to lie to the compiler (cast) to do so.


    Where is concept of "lying to the compiler" defined in the standard?

    >The wording is clear once you lie to the compiler you are in the land
    >of undefined behaviour.


    I am pretty sure you are wrong, but I do not intend to enter an
    endless discussion about that. As I said, the wording is so confusing
    that one cannot rely on compiler writers all interpreting this in the
    same way, so I have to stick to the safe interpretation anyway.
    copx, Jan 6, 2011
    #11
  12. copx

    Tim Rentsch Guest

    writes:

    > copx <> wrote:
    >>
    >> Here's some compile-ready code which illustrates the issue:
    >>
    >> #include <stdio.h>
    >>
    >> void foo(const int *c)
    >> {
    >> *((int *)c) = 'B';
    >> }
    >>
    >>
    >> int main(void)
    >> {
    >> int a = 'A';
    >>
    >> foo(&a);
    >> putchar(a);
    >> return 0;
    >> }
    >>
    >> ====
    >> Result: no warnings, prints 'B';

    >
    > It might just as well have printed 'A'. You have lied to the compiler
    > by declaring that foo() does not modify what its argument points to but
    > going ahead and doing so anyway. The compiler is permitted to believe
    > the declaration but is not required to, so either result is acceptable.
    > The code is not strictly conforming, but does not violate any
    > constraints so no diagnostics are required. It also does not contain
    > undefined behavior, just unspecified behavior.


    With all due respect, this analysis is not correct. All of the
    operations involved are well-defined, and none of the statements
    or expressions rely on unspecified behavior (not counting sending
    out just a single character to stdout without a trailing \n, but
    that's not what is being discussed). As far as the Standard
    goes, declaring a parameter to be of type (const int *) does not
    impose any restrictions as to whether the function is allowed to
    modify the pointed-to object. The cast to (int *) is guaranteed
    to work (in this code), and no effective type rules are violated.
    The program is not strictly conforming because of not sending out
    a full line of output, but aside from that I don't see any reason
    why it isn't.
    Tim Rentsch, Jan 6, 2011
    #12
  13. copx

    Tim Rentsch Guest

    Ian Collins <> writes:

    > On 01/ 7/11 10:43 AM, copx wrote:
    >>
    >> The standard only says "through that pointer" notice the "that".
    >> I can copy the value of the const pointer to a non-const pointer
    >> and then use this newly created pointer to modify the object thus
    >> the object is never actually modified "through that pointer".

    >
    > Yes you can, but you have to lie to the compiler (cast) to do so.
    >
    >> The exact, literal meaning of what the standard says validates the
    >> behavior of GCC IMO, but the wording of the standard is so horribly
    >> confusing here that I wouldn't be surprised if other compilers interpret
    >> this mess in a different way.

    >
    > The wording is clear: once you lie to the compiler you are in the land
    > of undefined behaviour.


    It would be most helpful if you would post a response
    supporting these statements, citing those sections
    of the Standard that are pertinent.
    Tim Rentsch, Jan 6, 2011
    #13
  14. copx

    Ian Collins Guest

    On 01/ 7/11 11:56 AM, Tim Rentsch wrote:
    > Ian Collins<> writes:
    >
    >> On 01/ 7/11 10:43 AM, copx wrote:
    >>>
    >>> The standard only says "through that pointer" notice the "that".
    >>> I can copy the value of the const pointer to a non-const pointer
    >>> and then use this newly created pointer to modify the object thus
    >>> the object is never actually modified "through that pointer".

    >>
    >> Yes you can, but you have to lie to the compiler (cast) to do so.
    >>
    >>> The exact, literal meaning of what the standard says validates the
    >>> behavior of GCC IMO, but the wording of the standard is so horribly
    >>> confusing here that I wouldn't be surprised if other compilers interpret
    >>> this mess in a different way.

    >>
    >> The wording is clear: once you lie to the compiler you are in the land
    >> of undefined behaviour.

    >
    > It would be most helpful if you would post a response
    > supporting these statements, citing those sections
    > of the Standard that are pertinent.


    Maybe, but it's a lovely day and there's a beer with my name on it down
    on the beach.

    While I'm away, consider the case where the address passed is in read
    only memory.

    --
    Ian Collins
    Ian Collins, Jan 6, 2011
    #14
  15. copx

    Tim Rentsch Guest

    Ian Collins <> writes:

    > On 01/ 7/11 11:56 AM, Tim Rentsch wrote:
    >> Ian Collins<> writes:
    >>
    >>> On 01/ 7/11 10:43 AM, copx wrote:
    >>>>
    >>>> The standard only says "through that pointer" notice the "that".
    >>>> I can copy the value of the const pointer to a non-const pointer
    >>>> and then use this newly created pointer to modify the object thus
    >>>> the object is never actually modified "through that pointer".
    >>>
    >>> Yes you can, but you have to lie to the compiler (cast) to do so.
    >>>
    >>>> The exact, literal meaning of what the standard says validates the
    >>>> behavior of GCC IMO, but the wording of the standard is so horribly
    >>>> confusing here that I wouldn't be surprised if other compilers interpret
    >>>> this mess in a different way.
    >>>
    >>> The wording is clear: once you lie to the compiler you are in the land
    >>> of undefined behaviour.

    >>
    >> It would be most helpful if you would post a response
    >> supporting these statements, citing those sections
    >> of the Standard that are pertinent.

    >
    > Maybe, but it's a lovely day and there's a beer with my name on it
    > down on the beach.
    >
    > While I'm away, consider the case where the address passed is in read
    > only memory.


    That circumstance hold in this case, as another posting from copx in
    this thread makes clear. Certainly it is true that if a pointer to
    an object that was defined as const-qualified is casted and used to
    store then the resulting behavior is undefined. The question,
    however, is what happens when a pointer to a non-const-qualified
    object is converted to a pointer to a const-qualified type, which is
    subsequently converted back to the original type and then used to
    store. The behavior in such circumstances is well-defined, not
    undefined. The reasoning about casting being lying to the compiler
    is bogus; there is nothing wrong with this casting in the case
    under consideration.
    Tim Rentsch, Jan 6, 2011
    #15
  16. copx

    Alan Curry Guest

    In article <ig46ve$7oj$>, copx <> wrote:
    >
    >#include <stdio.h>
    >
    >void foo(const int *c)
    >{
    > *((int *)c) = 'B';
    >}


    Regardless of it being legal, this is a crappy thing to do, and there is a
    gcc option to warn about it: -Wcast-qual

    --
    Alan Curry
    Alan Curry, Jan 6, 2011
    #16
  17. copx

    Thad Smith Guest

    On 1/6/2011 2:43 PM, copx wrote:

    > Digging further I could only find this:
    > ==
    > const int *ptr_to_constant;
    > ...
    > The contents of anyobject pointed to by ptr_to_constant shall
    > not be modiï¬ed through that pointer,
    > ==


    Unfortunately, that wording is in an _example_ in section 6.7.9.1. Examples are
    not normative.

    --
    Thad
    Thad Smith, Jan 7, 2011
    #17
  18. Thad Smith <> writes:

    > On 1/6/2011 2:43 PM, copx wrote:
    >
    >> Digging further I could only find this:
    >> ==
    >> const int *ptr_to_constant;
    >> ...
    >> The contents of anyobject pointed to by ptr_to_constant shall
    >> not be modiï¬ed through that pointer,
    >> ==

    >
    > Unfortunately, that wording is in an _example_ in section 6.7.9.1.
    > Examples are not normative.


    I don't think that matters. Normative text backs up that statement.

    The key part being "that pointer". That pointer can't be used but other
    pointers constructed from that pointer may permit modification of the
    pointed-to object.

    --
    Ben.
    Ben Bacarisse, Jan 7, 2011
    #18
  19. "copx" <> writes:

    > "Ike Naar" wrote in message
    > news:...
    >>The code has undefined behaviour.
    >>
    >>6.7.3
    >>5 If an attempt is made to modify an object defined with a
    >>const-qualified type through use of an lvalue with non-const-qualified
    >>type, the behavior is undefined.

    >
    > I read the same section of the standard and this doesn't support
    > your statement IMO. The standard talks about OBJECTS with
    > a const-qualified type NOT about const-qualified references to
    > non-const-qualified objects. I.e. this only means that modifying a
    > "const int" is undefined, const-qualified references to
    > non-const-qualified objects aren't mentioned here.
    >
    > Digging further I could only find this:
    > ==
    > const int *ptr_to_constant;
    > ..
    > The contents of anyobject pointed to by ptr_to_constant shall
    > not be modiï¬ed through that pointer,
    > ==
    >
    > Then I had to reference an entirely different section of the
    > standard to figure out the technical definition of "shall not".


    This is one reason why HTML would be helpfull. Hyperlinks can be very
    usefull here, since 'shall' word could have a different font, meaning
    it's something special, and selecting (clicking or whatever) would bring
    you to the definition instantaneous. And going back to your initial
    reading is just a matter or clicking to 'Back'.

    Is there any C drafts in HTML format ?

    [...]

    > The exact, literal meaning of what the standard says validates the
    > behavior of GCC IMO, but the wording of the standard is so horribly
    > confusing here that I wouldn't be surprised if other compilers
    > interpret this mess in a different way.


    Hey, welcome to the cruel C world.

    --
    Francis
    Francis Moreau, Jan 7, 2011
    #19
  20. "christian.bau" <> writes:

    [...]

    > For example:
    >
    > int i; const int* p = &i; * (int *) p = 1;
    >
    > is perfectly fine, but
    >
    >
    > const int i; const int* p = &i; * (int *) p = 1;
    >
    > is undefined behaviour. The first doesn't modify a const object, the
    > second one does. Use "const int* restrict" instead:
    >
    > int i; const int* restrict p = &i; * (int *) p = 1; // Undefined
    > behaviour
    >


    Could you argument your last example ?

    I don't see why adding 'restrict' qualifier invokes undefined
    behaviour. For me, the cast is defined and the effective rules are
    respected.

    The only thing it would do is to obfuscate your point.

    --
    Francis
    Francis Moreau, Jan 7, 2011
    #20
    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,099
  2. Ben Bacarisse

    Re: Few questions about casting away const.

    Ben Bacarisse, Mar 4, 2014, in forum: C Programming
    Replies:
    0
    Views:
    70
    Ben Bacarisse
    Mar 4, 2014
  3. Kaz Kylheku

    Re: Few questions about casting away const.

    Kaz Kylheku, Mar 4, 2014, in forum: C Programming
    Replies:
    0
    Views:
    92
    Kaz Kylheku
    Mar 4, 2014
  4. Keith Thompson

    Re: Few questions about casting away const.

    Keith Thompson, Mar 4, 2014, in forum: C Programming
    Replies:
    1
    Views:
    78
    Ben Bacarisse
    Mar 5, 2014
  5. James Kuyper

    Re: Few questions about casting away const.

    James Kuyper, Mar 4, 2014, in forum: C Programming
    Replies:
    15
    Views:
    135
    Tim Rentsch
    Mar 29, 2014
Loading...

Share This Page