What's the point of const pointers?

后端 未结 17 1826
粉色の甜心
粉色の甜心 2020-11-30 17:28

I\'m not talking about pointers to const values, but const pointers themselves.

I\'m learning C and C++ beyond the very basic stuff and just until today I realized t

相关标签:
17条回答
  • 2020-11-30 17:34

    int iVal = 10; int *const ipPtr = &iVal;

    Just like a normal const variable, a const pointer must be initialized to a value upon declaration, and its value can not be changed.

    This means a const pointer will always point to the same value. In the above case, ipPtr will always point to the address of iVal. However, because the value being pointed to is still non-const, it is possible to change the value being pointed to via dereferencing the pointer:

    *ipPtr = 6; // allowed, since pnPtr points to a non-const int

    0 讨论(0)
  • 2020-11-30 17:36

    Same question can be asked about any other type (not just pointers):

    /* Why is n const? */
    const char *expand(const int n) {
        if (n == 1) return "one";
        if (n == 2) return "two";
        if (n == 3) return "three";
        return "many";
    }
    
    0 讨论(0)
  • 2020-11-30 17:36

    Your question is really more about why define any variable as a const not just const pointer parameter to a function. The same rules apply here as when you define any variable as constant, if its a parameter to function or member variable or a local variable.

    In your particular case, functionally it doesn't make difference like in many other cases when you declare a local variable as const but it does put a restriction that you can't modify this variable.

    0 讨论(0)
  • 2020-11-30 17:41

    There is a lot to the const keyword, it is a rather complex one. Generally, adding a lot of const to your program is considered good programming practice, search the web for "const correctness" and you'll find plenty of info about that.

    The const keyword is a so-called "type qualifier", others are volatile and restrict. At least volatile follows the same (confusing) rules as const.


    First of all, the const keyword serves two purposes. The most obvious one is to protect data (and pointers) from intentional or accidental misuse by making them read-only. Any attempt to modify a const variable will be spotted by the compiler at compile-time.

    But there is also another purpose in any system with read-only memory, namely to ensure that a certain variable is allocated inside such memory - it could be EEPROM or flash for example. These are known as non-volatile memories, NVM. A variable allocated in NVM will still of course follow all the rules of a const variable.

    There are several different ways to use the const keyword:

    Declare a constant variable.

    This can be done either as

    const int X=1; or
    int const X=1;
    

    These two forms are completely equivalent. The latter style is considered bad style and should not be used.

    The reason why the second row is considered bad style, is probably because "storage-class specifiers" such as static and extern also can be declared after the actual type, int static etc. But doing so for storage-class specifiers is labelled as an obsolete feature by the C committee (ISO 9899 N1539 draft, 6.11.5). Therefore, for the sake of consistency one should not write type qualifiers in that manner either. It serves no other purpose but to confuse the reader anyhow.

    Declare a pointer to a constant variable.

    const int* ptr = &X;
    

    This means that the contents of 'X' cannot be modified. This is the normal way you declare pointers like this, mainly as part of function parameters for "const correctness". Because 'X' doesn't actually have to be declared as const, it could be any variable. In other words you can always "upgrade" a variable to const. Technically, C also allows downgrading from const to a plain variable by explicit typecasts, but doing so is considered bad programming and compilers usually give warnings against it.

    Declare a constant pointer

    int* const ptr = &X;
    

    This means that the pointer itself is constant. You can modify what it points at, but you cannot modify the pointer itself. This doesn't have many uses, there are a few, like ensuring that a pointer-pointed-at (pointer-to-pointer) doesn't have it's address changed while passed as parameter to a function. You'll have to write something not-too-readable like this:

    void func (int*const* ptrptr)
    

    I doubt many C programmers can get the const and * right in there. I know I can't - I had to check with GCC. I think that's why you rarely ever see that syntax for pointer-to-pointer, even though it is considered good programming practice.

    Constant pointers can also be used to ensure that the pointer variable itself is declared in read-only memory, for example you could want to declare some sort of pointer-based lookup table and allocate it in NVM.

    And of course, as indicated by other answers, constant pointers can also be used to enforce "const correctness".

    Declare a constant pointer to constant data

    const int* const ptr=&X;
    

    This is the two pointer types described above combined, with all attributes of them both.

    Declare a read-only member function (C++)

    Since this is tagged C++, I should also mention that you can declare member functions of a class as const. This means that the function isn't allowed to modify any other member of the class when it is called, which both prevents the programmer of the class from accidental errors but also informs the caller of the member function that they won't be messing anything up by calling it. The syntax is:

    void MyClass::func (void) const;
    
    0 讨论(0)
  • 2020-11-30 17:41

    I believe this would prevent code from incrementing or decrementing the pointer within the function body.

    0 讨论(0)
  • 2020-11-30 17:42

    ...today I realized that pointers are passed by value to functions, which makes sense.

    (imo) it really doesn't make sense as the default. the more sensible default is to pass as non-reassignable pointer (int* const arg). that is, i would have preferred that pointers passed as arguments were implicitly declared const.

    So what's the advantage of const?

    the advantage is that it's easy enough and sometimes unclear when you do modify the address the argument points to, such that you can introduce a bug when it is not const rather easily. altering the address is atypical. it's clearer to create a local variable if your intent is to modify the address. as well, raw pointer manipulation is an easy way to introduce bugs.

    so it's clearer to pass by immutable address and create a copy (in those atypical cases) when you want to alter the address the argument points to:

    void func(int* const arg) {
        int* a(arg);
        ...
        *a++ = value;
    }
    

    adding that local is virtually free, and it reduces the chance for errors, while improving readability.

    at a higher level: if you are manipulating the argument as an array, it's typically clearer and less error prone to the client to declare the argument as a container/collection.

    in general, adding const to values, arguments, and addresses is a good idea because you don't always realize the side effects, which the compiler happily enforces. therefore, it's as useful as const as used in other several other cases (e.g. the question is similar to 'Why should I declare values const?'). fortunately, we also have references, which cannot be reassigned.

    0 讨论(0)
提交回复
热议问题