const really constant?

Discussion in 'C Programming' started by Mantorok Redgormor, Sep 19, 2003.

  1. Is const really constant?

    And on an OT note: how can I post with a modified e-mail address so I
    don't get so much spam?
    Mantorok Redgormor, Sep 19, 2003
    #1
    1. Advertising

  2. On 19 Sep 2003 13:38:37 -0700
    (Mantorok Redgormor) wrote:
    > Is const really constant?


    No, const is a keyword. A variable defined to be const may not change value
    after definition.

    > And on an OT note: how can I post with a modified e-mail address so I
    > don't get so much spam?


    Read your newsreader's documentation and improvise.

    --
    char*x(c,k,s)char*k,*s;{if(!k)return*s-36?x(0,0,s+1):s;if(s)if(*s)c=10+(c?(x(
    c,k,0),x(c,k+=*s-c,s+1),*k):(x(*s,k,s+1),0));else c=10;printf(&x(~0,0,k)[c-~-
    c+"1"[~c<-c]],c);}main(){x(0,"^[kXc6]dn_eaoh$%c","-34*1'.+(,03#;+,)/'///*");}
    Pieter Droogendijk, Sep 19, 2003
    #2
    1. Advertising

  3. Mantorok Redgormor

    Alex Guest

    Mantorok Redgormor <> wrote:
    > Is const really constant?


    Like Chris Torek always says, 'const' in C means 'read-only'. It
    does not act as a constant when a constant expression is expected,
    nor does it completely preclude modifications to the variable.

    Consider:

    const int x = 10;

    int array[x]; /* ilegal, not constant expression */

    and

    const int x = 10;
    int *p = (int *)&x;

    *p = 2; /* ooops, just changed x */

    Alex
    Alex, Sep 19, 2003
    #3
  4. Mantorok Redgormor

    Nick Austin Guest

    On 19 Sep 2003 21:02:05 GMT, Alex <> wrote:

    > const int x = 10;
    > int *p = (int *)&x;
    >
    > *p = 2; /* ooops, just changed x */


    Is that not UB?

    N869:
    "J.2 Undefined behavior

    [snip]

    -- An attempt is made to modify an object defined with a
    const-qualified type through use of an lvalue with non-
    const-qualified type."

    Nick.
    Nick Austin, Sep 19, 2003
    #4
  5. Mantorok Redgormor

    Alex Guest

    Nick Austin <> wrote:
    > On 19 Sep 2003 21:02:05 GMT, Alex <> wrote:


    >> const int x = 10;
    >> int *p = (int *)&x;
    >>
    >> *p = 2; /* ooops, just changed x */


    > Is that not UB?


    > N869:
    > "J.2 Undefined behavior


    > [snip]


    > -- An attempt is made to modify an object defined with a
    > const-qualified type through use of an lvalue with non-
    > const-qualified type."


    Looks like you're right. Sorry.

    Alex
    Alex, Sep 19, 2003
    #5
  6. Hi,
    "Alex" <> wrote in message
    news:bkg0dq$1el38$-berlin.de...
    > Nick Austin <> wrote:
    > > On 19 Sep 2003 21:02:05 GMT, Alex <> wrote:

    >
    > >> const int x = 10;
    > >> int *p = (int *)&x;
    > >>
    > >> *p = 2; /* ooops, just changed x */

    >
    > > Is that not UB?

    >
    > > N869:
    > > "J.2 Undefined behavior

    >
    > > [snip]

    >
    > > -- An attempt is made to modify an object defined with a
    > > const-qualified type through use of an lvalue with non-
    > > const-qualified type."

    >
    > Looks like you're right. Sorry.


    Yes, however the following is not UB and demonstrates the
    same issue:

    int f( int* a, int const* b )
    {
    *a += *b;
    return *b; // must re-read *b, may have changed
    }

    int main()
    {
    int i = 10;
    printf( "%d\n", f(&i,&i) );
    return 0;
    }

    This program must print 20, and the compiler may
    not optimize the two accesses to *b within f().
    Const guarantees that the value cannot be modified
    through the variable/pointer itself. But the
    compiler cannot assume that the value will remain
    unchanged.

    This is why a variable can be both const and volatile.

    This is also related to why 'restrict' was introduced
    in the C99 standard ...


    Kind regards,
    Ivan
    --
    http://ivan.vecerina.com
    Ivan Vecerina, Sep 20, 2003
    #6
  7. "Nick Austin" <> wrote in message
    news:...
    > On 19 Sep 2003 21:02:05 GMT, Alex <> wrote:
    >
    > > const int x = 10;
    > > int *p = (int *)&x;
    > >
    > > *p = 2; /* ooops, just changed x */

    >
    > Is that not UB?
    >
    > N869:
    > "J.2 Undefined behavior
    >
    > [snip]
    >
    > -- 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 normative reference is 6.7.3p5

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

    --
    Peter
    Peter Nilsson, Sep 20, 2003
    #7
  8. Mantorok Redgormor

    John L Guest

    Alex wrote
    > Mantorok Redgormor <> wrote:
    > > Is const really constant?


    > Consider:
    >
    > const int x = 10;
    >
    > int array[x]; /* ilegal, not constant expression */
    >
    > and
    >
    > const int x = 10;
    > int *p = (int *)&x;


    Sorry to digress, but is the cast above necessary? Isn't

    int *p = &x;

    correct?

    Thanks!
    John L, Sep 20, 2003
    #8
  9. > > const int x = 10;
    > > int *p = (int *)&x;

    >
    > Sorry to digress, but is the cast above necessary? Isn't
    >
    > int *p = &x;
    >
    > correct?


    I believe the reason is that &x will return a pointer that is of type "const
    int *". As p doesn't have a const modifier, the assignment will be illegal.
    The cast attempts to remove that modifier before assignment. As mentioned
    by others, this is undefined in C, but quite legal as I understand (at least
    with Microsoft's implementation) in C++.

    Mike

    --
    Michael Winter
    M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)
    Michael Winter, Sep 20, 2003
    #9
  10. On Sat, 20 Sep 2003, Michael Winter wrote:
    >
    > > > const int x = 10;
    > > > int *p = (int *)&x;

    > >
    > > Sorry to digress, but is the cast above necessary? Isn't
    > > int *p = &x;
    > > correct?

    >
    > I believe the reason is that &x will return a pointer that is of type "const
    > int *". As p doesn't have a const modifier, the assignment will be illegal.


    That's correct. The address of an 'int' is a pointer to 'int'; the
    address of a 'const int' is a pointer to 'const int'.

    > The cast attempts to remove that modifier before assignment. As mentioned
    > by others, this is undefined in C,


    Not quite. The initialization

    const int x = 42;
    int *p = (int *)&x;

    is absolutely legal in C. What's *not* legal is following that
    up with

    (*p) = 43;

    because that tries to modify a const-qualified value. And
    since it would be burdensome to make the compiler catch all
    such errors, the standard simply calls the result of the
    modification "undefined behavior" and leaves it at that.

    > but quite legal as I understand (at least
    > with Microsoft's implementation) in C++.


    I seriously doubt this. My impression is that C++ is *more*
    strict about type-safety than C, not less.

    -Arthur
    Arthur J. O'Dwyer, Sep 20, 2003
    #10
  11. On Sat, 20 Sep 2003, Arthur J. O'Dwyer wrote:
    >
    > On Sat, 20 Sep 2003, Michael Winter wrote:
    > >
    > > I believe the reason is that &x will return a pointer that is of type

    "const
    > > int *". As p doesn't have a const modifier, the assignment will be

    illegal.
    >
    > That's correct. The address of an 'int' is a pointer to 'int'; the
    > address of a 'const int' is a pointer to 'const int'.
    >
    > > The cast attempts to remove that modifier before assignment. As

    mentioned
    > > by others, this is undefined in C,

    >
    > Not quite. The initialization
    >
    > const int x = 42;
    > int *p = (int *)&x;
    >
    > is absolutely legal in C. What's *not* legal is following that
    > up with
    >
    > (*p) = 43;
    >
    > because that tries to modify a const-qualified value. And
    > since it would be burdensome to make the compiler catch all
    > such errors, the standard simply calls the result of the
    > modification "undefined behavior" and leaves it at that.


    I glossed over that. As I said, others mentioned what would occur if you
    tried to modify a const-qualified variable through a pointer.


    [OT from here...]

    > > but quite legal as I understand (at least
    > > with Microsoft's implementation) in C++.

    >
    > I seriously doubt this. My impression is that C++ is *more*
    > strict about type-safety than C, not less.


    That's a matter of debate. In addition to the C-style cast, C++ includes
    four other casting operators.

    dynamic_cast *is* strict - a run-time type check is performed on the
    variable being cast [what checks, I'll omit]. If the cast fails, a bad_cast
    exception is thrown.

    static_cast checks the validity of the cast based on the information that
    the developer provides (original and desired type). There was no mention of
    exceptions in the case of a failure here, but there is the possibility of
    undefined behaviour.

    reinterpret_cast allows you to convert any pointer into any other pointer -
    there are no checks what-so-ever.

    const_cast allows you to strip the const, volatile and __unaligned
    attributes. Here, a write through a cast pointer (including one that was
    previously const) *might* be undefined, but it depends on the type of
    object. I don't have any more information on that: Microsoft's
    documentation stops there (there was no "Microsoft-specific" marking, so I
    assume that it is standard C++).

    I do have to admit that I forgot the "might be undefined" part (I usually
    stick to C-style casts, and I've never cast away a const-qualifier anyway).
    However, it's not quite so clear cut as others present it in C, nor is C++
    any more type-safe than C, unless the developer chooses to make it so with
    the more reliable casts.

    Mike

    --
    Michael Winter
    M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)
    Michael Winter, Sep 20, 2003
    #11
  12. On Sat, 20 Sep 2003 16:56:08 GMT, "Michael Winter"
    <M.Winter@[no-spam]blueyonder.co.uk> wrote:

    > On Sat, 20 Sep 2003, Arthur J. O'Dwyer wrote:

    <snip>
    > > Not quite. The initialization
    > >
    > > const int x = 42;
    > > int *p = (int *)&x;
    > >
    > > is absolutely legal in C. What's *not* legal is following that
    > > up with
    > >
    > > (*p) = 43;
    > >
    > > because that tries to modify a const-qualified value. And
    > > since it would be burdensome to make the compiler catch all
    > > such errors, the standard simply calls the result of the
    > > modification "undefined behavior" and leaves it at that.

    >

    And just to be clear, any other storage or computation (assignment,
    passing or returning, addtion/subtraction within an array) on the
    deconstified pointer is legal; it is only dereference, or subscripting
    which includes dereference, that is UB.

    > I glossed over that. As I said, others mentioned what would occur if you
    > tried to modify a const-qualified variable through a pointer.
    >

    If the pointer is to const, it is a constraint violation and diagnosed
    (in C; in C++ it is a violation whose diagnosis is not waived, same
    result). If the pointer has had const cast away, it is UB.

    >
    > [OT from here...]


    <snip>
    > > I seriously doubt this. My impression is that C++ is *more*
    > > strict about type-safety than C, not less.

    >
    > That's a matter of debate. In addition to the C-style cast, C++ includes
    > four other casting operators. <snipped except>
    > If the [dynamic_cast] fails, a bad_cast exception is thrown.
    >

    For a reference; for a pointer it gives a null pointer.

    > const_cast allows you to strip the const, volatile and __unaligned
    > attributes. Here, a write through a cast pointer (including one that was
    > previously const) *might* be undefined, but it depends on the type of
    > object. I don't have any more information on that: Microsoft's
    > documentation stops there (there was no "Microsoft-specific" marking, so I
    > assume that it is standard C++).
    >

    It's standard, except for __unaligned as you might guess. Storing to
    an object that was *defined* as const (and not mutable) is UB, as in
    C: 7.1.5.1[dcl.type.cv]p4, as referenced by 5.2.11[expr.const.cast]p7,
    and extended to deconstructed memory in 3.8[basic.life]p9; in C the
    lifetime of an object is from allocation to deallocation, but in C++
    for a nontrivial class type only from construction to destruction, so
    this makes the const rule apply from allocation to deallocation.

    If you create a const pointer to an object that is actually nonconst,
    as can easily be done implicitly, then cast away const and store
    through the result, that is well-defined and works in both C and C++.

    Also, in C++ but not C a const variable of integer or enumeration type
    initialized by a constant expression can be used in a constant
    expression. This means that if you do illegally store to such a
    variable, after/by forming a nonconst pointer to it, and the
    implementation doesn't trap and actually does the store -- one
    permitted option under UB -- it is rather likely that the stored value
    will not be used in what appear to be subsequent fetches of it. A C
    compiler may do this same optimization if it likes, under the (very)
    broad aegis of UB, but it isn't encouraged the way C++ is.

    > I do have to admit that I forgot the "might be undefined" part (I usually
    > stick to C-style casts, and I've never cast away a const-qualifier anyway).
    > However, it's not quite so clear cut as others present it in C, nor is C++
    > any more type-safe than C, unless the developer chooses to make it so with
    > the more reliable casts.
    >

    It is in several places.

    C++ does not allow implicit conversion from base to derived, which is
    a feature that does not exist in C, but extends this principle to
    prohibit implicit conversion of void* to any other data*, which C
    allows; this is a FDiscussedFeature(?) on clc.

    C++ considers enum types (and their values) distinct and does not
    allow implicit conversion from an integer. C considers enums just
    integers of some implementation-dependent size.

    Optional arguments, and to some extent templates, allow some functions
    with varying signatures to be written typesafely that would require
    less-safe varargs in C, although that option still exists in C++.

    C++ outlawed implicit int (and implicit function declaration) first,
    but C99 has matched it. C++ has only the prototype syntax for
    functions, not the less-safe K&R1 syntax still allowed in C.

    C++ prohibited unvalued return for nonvoid functions first, but C99
    has matched it; C++ also makes it UB immediately when falling off the
    end of a nonvoid function, instead of trying to use the indeterminate
    return value as in C, and this is often easier to diagnose though not
    required. C++ also allows a return "value" of void type in a void
    function, which is useful for templates, but not really needed in C.

    C++ retains C's array/pointer duality and pointer arithmetic, which
    are in practice impractical to make safe, but offers the option of
    std::vector or other array-like classes and "smart" pointers, and in
    particular std::string or other string classes for the area that has
    proven most frequently (IMJ) troublesome in C.

    But yes, the new more specific -- and more visible in source -- casts
    are an important contributor to typesafety in C++.

    - David.Thompson1 at worldnet.att.net
    Dave Thompson, Sep 29, 2003
    #12
    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,101
  2. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  3. Rohit kumar Chandel

    Is const really const?

    Rohit kumar Chandel, Dec 17, 2007, in forum: C Programming
    Replies:
    29
    Views:
    816
    James Kuyper
    Dec 20, 2007
  4. 0m
    Replies:
    26
    Views:
    1,114
    Tim Rentsch
    Nov 10, 2008
  5. paulo
    Replies:
    9
    Views:
    707
    James Kanze
    Mar 6, 2009
Loading...

Share This Page