const variables

Discussion in 'C Programming' started by junky_fellow@yahoo.co.in, Dec 29, 2006.

  1. Guest

    Hi guys,

    Consider the following statements.

    const int *ptr; /* ie the contents pointed to by ptr cannot be
    changed */

    My question is how/who prevents the contents from being modified ?
    Is it the C compiler that would give compile time error while trying to
    change the contents ? Or is it the implementation that would somehow
    prevent the contents from being modified during run time ?

    Now consider the following two statements:

    const int *ptr; /* line #1 */
    int *tmp = ptr; /* line #2 */
    *tmp = 100; /* line #3 , Is this valid ? */

    Can we change the contents of "tmp" as done is line #3. Will the C
    compiler generate warning on line #3. Will this cause some exception
    during run time ?

    One more question:
    const int *ptr = malloc(4 * sizeof(int));
    free(ptr); /* gives warning */

    While freeing the memory, the compiler generated warning. What is the
    reason behind that ? Can't this memory be freed ?


    thanks a lot for any help in advance ...
     
    , Dec 29, 2006
    #1
    1. Advertising

  2. Eric Sosman Guest

    wrote:
    > Hi guys,
    >
    > Consider the following statements.
    >
    > const int *ptr; /* ie the contents pointed to by ptr cannot be
    > changed */


    Almost: The pointed-to int cannot be changed through ptr,
    but could be changed by some other pathway:

    int target = 0;
    const int *ptr = ⌖
    *ptr = 42; /* compile error */
    target = 42; /* no problem */

    > My question is how/who prevents the contents from being modified ?
    > Is it the C compiler that would give compile time error while trying to
    > change the contents ? Or is it the implementation that would somehow
    > prevent the contents from being modified during run time ?


    The former. Now, if the target itself is also const, any
    attempt to change it produces undefined behavior. For example,
    an implementation might place the target in read-only memory
    and might cause a trap on any attempt to write to it. Or it
    might simply ignore the attempt to write and proceed merrily
    and silently on its way. Or the write might succeed, producing
    mysteries later on. Or the attempt to write might make demons
    fly out of your nose: in theory, at least, Anything Can Happen.

    > Now consider the following two statements:
    >
    > const int *ptr; /* line #1 */
    > int *tmp = ptr; /* line #2 */
    > *tmp = 100; /* line #3 , Is this valid ? */
    >
    > Can we change the contents of "tmp" as done is line #3. Will the C
    > compiler generate warning on line #3. Will this cause some exception
    > during run time ?


    The compiler will object to line #2, because you cannot
    "subtract" a qualifier silently. The compiler's objection can
    be silenced with a cast:

    int *tmp = (int*)ptr;

    (Of course, the compiler is permitted to issue warnings for
    anything at all, and may still issue a warning for this line.
    It must accept the revised code, though, even though it can
    reject the original.)

    At run time, the behavior depends on what ptr and tmp point
    at. If the target is const the behavior of line #3 is undefined,
    but if it is non-const the assignment works normally.

    > One more question:
    > const int *ptr = malloc(4 * sizeof(int));
    > free(ptr); /* gives warning */
    >
    > While freeing the memory, the compiler generated warning. What is the
    > reason behind that ? Can't this memory be freed ?


    When you free() a block of memory, you make it available
    for re-use by a subsequent malloc(). Even if free() itself
    does not modify the memory block, it exposes the block to
    being modified later on. Hence, free(ptr) violates the promise
    not to use ptr to modify the memory it points at.

    You can still free() the memory, but not by using ptr as
    it stands. One way is

    free ((void*)ptr);

    Even though ptr is const-qualified, (void*)ptr is not. See
    the change to line #2 in the earlier example.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Dec 29, 2006
    #2
    1. Advertising

  3. Guest

    Eric Sosman wrote:
    > wrote:
    > > Hi guys,
    > >
    > > Consider the following statements.
    > >
    > > const int *ptr; /* ie the contents pointed to by ptr cannot be
    > > changed */

    >
    > Almost: The pointed-to int cannot be changed through ptr,
    > but could be changed by some other pathway:
    >
    > int target = 0;
    > const int *ptr = ⌖
    > *ptr = 42; /* compile error */
    > target = 42; /* no problem */
    >
    > > My question is how/who prevents the contents from being modified ?
    > > Is it the C compiler that would give compile time error while trying to
    > > change the contents ? Or is it the implementation that would somehow
    > > prevent the contents from being modified during run time ?

    >
    > The former. Now, if the target itself is also const, any
    > attempt to change it produces undefined behavior. For example,
    > an implementation might place the target in read-only memory
    > and might cause a trap on any attempt to write to it. Or it
    > might simply ignore the attempt to write and proceed merrily
    > and silently on its way. Or the write might succeed, producing
    > mysteries later on. Or the attempt to write might make demons
    > fly out of your nose: in theory, at least, Anything Can Happen.
    >
    > > Now consider the following two statements:
    > >
    > > const int *ptr; /* line #1 */
    > > int *tmp = ptr; /* line #2 */
    > > *tmp = 100; /* line #3 , Is this valid ? */
    > >
    > > Can we change the contents of "tmp" as done is line #3. Will the C
    > > compiler generate warning on line #3. Will this cause some exception
    > > during run time ?

    >
    > The compiler will object to line #2, because you cannot
    > "subtract" a qualifier silently. The compiler's objection can
    > be silenced with a cast:
    >
    > int *tmp = (int*)ptr;
    >
    > (Of course, the compiler is permitted to issue warnings for
    > anything at all, and may still issue a warning for this line.
    > It must accept the revised code, though, even though it can
    > reject the original.)
    >
    > At run time, the behavior depends on what ptr and tmp point
    > at. If the target is const the behavior of line #3 is undefined,
    > but if it is non-const the assignment works normally.
    >
    > > One more question:
    > > const int *ptr = malloc(4 * sizeof(int));
    > > free(ptr); /* gives warning */
    > >
    > > While freeing the memory, the compiler generated warning. What is the
    > > reason behind that ? Can't this memory be freed ?

    >
    > When you free() a block of memory, you make it available
    > for re-use by a subsequent malloc(). Even if free() itself
    > does not modify the memory block, it exposes the block to
    > being modified later on. Hence, free(ptr) violates the promise
    > not to use ptr to modify the memory it points at.
    >
    > You can still free() the memory, but not by using ptr as
    > it stands. One way is
    >
    > free ((void*)ptr);
    >
    > Even though ptr is const-qualified, (void*)ptr is not. See
    > the change to line #2 in the earlier example.
    >


    Thank you Eric for the nice explanation.
     
    , Dec 30, 2006
    #3
  4. Guest

    Eric Sosman wrote:
    > wrote:
    > > Hi guys,
    > >
    > > Consider the following statements.
    > >
    > > const int *ptr; /* ie the contents pointed to by ptr cannot be
    > > changed */

    >
    > Almost: The pointed-to int cannot be changed through ptr,
    > but could be changed by some other pathway:
    >
    > int target = 0;
    > const int *ptr = ⌖
    > *ptr = 42; /* compile error */
    > target = 42; /* no problem */
    >
    > > My question is how/who prevents the contents from being modified ?
    > > Is it the C compiler that would give compile time error while trying to
    > > change the contents ? Or is it the implementation that would somehow
    > > prevent the contents from being modified during run time ?

    >
    > The former. Now, if the target itself is also const, any
    > attempt to change it produces undefined behavior. For example,
    > an implementation might place the target in read-only memory
    > and might cause a trap on any attempt to write to it. Or it
    > might simply ignore the attempt to write and proceed merrily
    > and silently on its way. Or the write might succeed, producing
    > mysteries later on. Or the attempt to write might make demons
    > fly out of your nose: in theory, at least, Anything Can Happen.
    >
    > > Now consider the following two statements:
    > >
    > > const int *ptr; /* line #1 */
    > > int *tmp = ptr; /* line #2 */
    > > *tmp = 100; /* line #3 , Is this valid ? */
    > >
    > > Can we change the contents of "tmp" as done is line #3. Will the C
    > > compiler generate warning on line #3. Will this cause some exception
    > > during run time ?

    >
    > The compiler will object to line #2, because you cannot
    > "subtract" a qualifier silently. The compiler's objection can
    > be silenced with a cast:
    >
    > int *tmp = (int*)ptr;
    >
    > (Of course, the compiler is permitted to issue warnings for
    > anything at all, and may still issue a warning for this line.
    > It must accept the revised code, though, even though it can
    > reject the original.)
    >
    > At run time, the behavior depends on what ptr and tmp point
    > at. If the target is const the behavior of line #3 is undefined,
    > but if it is non-const the assignment works normally.
    >
    > > One more question:
    > > const int *ptr = malloc(4 * sizeof(int));
    > > free(ptr); /* gives warning */
    > >
    > > While freeing the memory, the compiler generated warning. What is the
    > > reason behind that ? Can't this memory be freed ?

    >
    > When you free() a block of memory, you make it available
    > for re-use by a subsequent malloc(). Even if free() itself
    > does not modify the memory block, it exposes the block to
    > being modified later on. Hence, free(ptr) violates the promise
    > not to use ptr to modify the memory it points at.
    >
    > You can still free() the memory, but not by using ptr as
    > it stands. One way is
    >
    > free ((void*)ptr);
    >
    > Even though ptr is const-qualified, (void*)ptr is not. See
    > the change to line #2 in the earlier example.
    >


    Thanks Eric for your reply. What I got from your reply is that, if we
    are trying to change any const value directly, the compiler will give
    error and the code will not be compiled. Secondly, the const value may
    be changed indirectly by some other ways, but in that case the
    behaviour is undefined ( An implementation may put the const thing in
    read only section and while changing it during run time through
    indirect ways, it might cause a trap ).

    The other thing that I wanted to know whether,
    const int *cptr;
    int *ptr;
    have different types ? Can we convert one type to other without a cast
    ?

    Also, what's wrong in doing,
    void *ptr;
    const int *ptr1;
    ptr = ptr1;
    I believe, "void *" is a generic pointer and any pointer type may be
    converted to void pointer without cast. Then, why compiler generates
    warning while doing "ptr = ptr1" ?

    Also, what is the difference between "unqualified type" and "qualified
    version of its type" ?
     
    , Dec 30, 2006
    #4
  5. Eric Sosman Guest

    wrote:
    > [...]
    >
    > The other thing that I wanted to know whether,
    > const int *cptr;
    > int *ptr;
    > have different types?


    They have different types: "const-qualified pointer to int"
    and "pointer to int," respectively.

    > Can we convert one type to other without a cast?


    `cptr = ptr' is fine ("adding" a qualifier is all right),
    but `ptr = cptr' is not ("subtracting" a qualifier needs a cast).

    > Also, what's wrong in doing,
    > void *ptr;
    > const int *ptr1;
    > ptr = ptr1;
    > I believe, "void *" is a generic pointer and any pointer type may be
    > converted to void pointer without cast. Then, why compiler generates
    > warning while doing "ptr = ptr1" ?


    Because you're trying to "subtract" the const qualifier.

    const void *ptr2;
    ptr2 = ptr1;

    would be fine.

    > Also, what is the difference between "unqualified type" and "qualified
    > version of its type" ?


    A "qualified" type has one or more "qualifiers" -- const,
    restrict, and/or volatile -- while an unqualified type has none.
    A qualified type has the same representation, same universe of
    values, same alignment requirements, blah, blah, blah, as the
    corresponding unqualified type, but the qualifiers specify
    "special handling" of various kinds.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Dec 30, 2006
    #5
    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,108
  2. Javier
    Replies:
    2
    Views:
    565
    James Kanze
    Sep 4, 2007
  3. 0m
    Replies:
    26
    Views:
    1,122
    Tim Rentsch
    Nov 10, 2008
  4. fungus
    Replies:
    13
    Views:
    892
    fungus
    Oct 31, 2008
  5. Replies:
    2
    Views:
    542
    Andrew Koenig
    Feb 9, 2009
Loading...

Share This Page