const pointer parameter assigned to a local variable inside a function

This is a discussion on const pointer parameter assigned to a local variable inside a function within the C Programming forums, part of the General Programming Boards category; Code: void func1(const int* p, int i) { int *q = p; if (*q==i) printf("very good"); } I have to ...

  1. #1
    Registered User
    Join Date
    Jul 2005
    Posts
    98

    const pointer parameter assigned to a local variable inside a function

    Code:
    void func1(const int* p, int i)
    {
      int *q = p;
      if (*q==i)
       printf("very good");
    }
    I have to qualify the declaration of q with 'const' in order to avoid a gcc warning. Why? By declaring *p a const, I am saying nothing inside the function modifies *p, and indeed nothing does. So why does gcc give me
    warning: initialization discards qualifiers from pointer target type
    ? Why does gcc discard the const-ness of *p? Yes, the function _may_ attempt to change *p through q, but the fact is it does not. And now gcc drops the const and actually the function now can change the value of *p!
    Now I can change *p through q and gcc does not complain about assigning a value to a read-only memory (though still with that "discards qualifiers " warning):
    Code:
    void func1(const int* p, int i)
    {
      int *q = p;
      *q = i;
    }

  2. #2
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Why does gcc discard the const-ness of *p?
    Because you tell it to.
    Last edited by Dave_Sinkula; 11-10-2005 at 09:13 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by Dave_Sinkula
    Code:
     const int *q = p;
    }
    That was exactly what I said: "I have to qualify the declaration of q with 'const' in order to avoid a gcc warning." And my question is: why? Do I misunderstand what "const" means?
    To make it more complicated, now I have this code:
    Code:
    const int * func1(const int* p, int i)
    {
      const int *q = p;
      if (*q==i)
        printf("very good");
      return p;
    }
    In the same spirit that I have to const-ify *q, I need to const-ify the return value of the function. That looks weird. And now if I have this:
    Code:
    int main()
    {
      int *j;
      *j = 1;
      j = func1(j, 2);
      printf("*j=%d\n", *j);
      *j = 4;
    }
    The compiler again gives me that warning. And this time I cannot avoid it because I need to change *j. I can't const-ify *j.

  4. #4
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    If you mean to change something, don't make it const.

    [edit]And this is UB:
    Code:
      *j = 1;
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  5. #5
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by Dave_Sinkula
    Because you tell it to.
    Did the C standard says one cannot assign a const pointed-to value (i.e. const *p) to another pointer (i.e. *q), or risk a warning? It appears to me that the only rule regarding const is that *p is not modified, and in this case it is not modified. So I should not get this warning. Am I right?

  6. #6
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    You can lie to the compiler to shut it up if you want, but this may be hazardous to your program's health.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  7. #7
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by Dave_Sinkula
    If you mean to change something, don't make it const.

    [edit]And this is UB:
    Code:
      *j = 1;
    I am forced to make it const! Based on my understanding of C, I should not be required to const-ify q, and that means I would not be foreced to const-ify the return value.

  8. #8
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Quote Originally Posted by Dave_Sinkula
    You can lie to the compiler to shut it up if you want, but this may be hazardous to your program's health.
    My question remains: Where in the C standard that says one cannot assign a const pointed-to value (i.e. const *p) to another pointer (i.e. *q)? Forget about lying to the compiler. If the compiler conforms with C, then it would not give this unnecessary warning, and nobody needs to lie to it. Is my understanding about the C standard wrong? Does it have a rule that says one cannot assign a const pointed-to value (i.e. const *p) to another pointer (i.e. *q)?

  9. #9
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    First you promise the compiler you're not going to modify what is pointed to by p. And then you break the promise and say, "To heck with that, I"ll modify what I want!", by saying that what q points to is modifiable. Gcc says, "Uh, take another look."
    Last edited by Dave_Sinkula; 11-10-2005 at 09:39 PM. Reason: ~/say/saying
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Sh!t. Gimme a minute (or so). I think the standard says something like, go ahead, but it's UB...

    [edit]
    Quote Originally Posted by 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.
    [edit=2]So this is the point at which you are giving license to UB:
    Code:
    int *q = p;
    Frankly, I'd like the compiler to tell me where I'm about to screw up.
    Last edited by Dave_Sinkula; 11-10-2005 at 09:37 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    OK, I found this on the web:

    If a pointer is declared as const, it can only be assigned another pointer declared as const. If the pointer is a parameter to a function and you want to assign it to some other pointer within that function (e.g., a local variable) then the local variable must also be const.

    I do not know whether the standard actually says this, or it is an interpretation of what the standard says. So, the warning has nothing to do with whether a const parameter is actually modified or not. It simply prohibits a const pointer to be assigned to a non-const pointer, even though the non-const pointer does not in fact change the pointed-to value. C is simply too lazy to check; it just outlaws it to save the effort, I guess.

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    You're asking your poor compiler, and the poor compiler writers, to make sure that you're not a total idiot. They try their best to warn you when you may be doing something stupid, but they don't forbid you from shooting yourself in the foot. Such is the nature of a language that assumes you know what you are doing.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    Registered User
    Join Date
    Jul 2005
    Posts
    98
    Such a restriction seems to produce some unintended undue inconvenience to the programmer in the following case:
    Code:
    typedef int t_compare_func(const void *, const void *);
    
    struct node *tree_search(struct node *root, const void *keyy, t_compare_func *comp)
    {
      struct node *cur_item;
      int result;
      if (root == NULL) return NULL;
      cur_item = root;
      while (cur_item != NULL) {
          result = (*comp)(cur_item->key, keyy);
          if (result == 0) 
             break;
          else if (result > 0) 
             cur_item = cur_item->left;
          else
             cur_item = cur_item->right;
      }
      return cur_item;
    }
    Here, I traverse the tree to find a node whose key member is the same as keyy. And the node found is returned. Nothing in the tree is ever modified. So naturally I would like to const-ify root. But then I am forced to also const-ify cur_item. And the return value also has to be const-ifed as a consequence. Now, (part of) the tree in the calling function cannot be modified! Therefore I have to give up const-ifying root even though nothing in the function modifies the tree. Can I avoid this side effect? Have I just found a legitimate use of const_cast here? O, const_cast is available in C++ only. I guess I need to just cast root like:
    cur_item = (struct node *)root;
    if I decalre root as a const parameter. Right?
    Last edited by hzmonte; 11-10-2005 at 10:24 PM.

  14. #14
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Ah, the real question.

    You can pass a non-const qualified value to a function with a const-qualified value. Going up doesn't hurt things, going down does.

    But since I can't compile your snippet, I'll refrain from commenting further. [It's getting late for me.]

    [edit]Do you intend to (potentially) modify root? If so, don't tell the compiler you won't. And the same goes for any aliases you may create.
    Last edited by Dave_Sinkula; 11-10-2005 at 10:15 PM.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  15. #15
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,006
    Quote Originally Posted by hzmonte
    I guess I need to just cast root like:
    cur_item = (struct node *)root;
    if I decalre root as a const parameter. Right?
    Lying is lying.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. In over my head
    By Shelnutt2 in forum C Programming
    Replies: 1
    Last Post: 07-08-2008, 06:54 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Including lib in a lib
    By bibiteinfo in forum C++ Programming
    Replies: 0
    Last Post: 02-07-2006, 01:28 PM
  4. c++ linking problem for x11
    By kron in forum Linux Programming
    Replies: 1
    Last Post: 11-19-2004, 09:18 AM
  5. Half-life SDK, where are the constants?
    By bennyandthejets in forum Game Programming
    Replies: 29
    Last Post: 08-25-2003, 11:58 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21