constness and pointers to pointers

后端 未结 4 448
时光取名叫无心
时光取名叫无心 2020-11-30 13:15

I\'m very much confused about the const keyword. I have a function accepting an array of strings as input parameter and a function accepting a variable number o

相关标签:
4条回答
  • 2020-11-30 13:47

    Actually if there is a function that accepts a const char** and you pass a char** , this can lead to a problematic situation and viceversa.

    In your specific case you expect that the memory is immutable, but it's not immutable and may change at any time. In a multithreading environment you would expect this memory to be thread safe, and as long as it's living in the stack or heap, you wouldn't need a mutex to access to it.

    All this is oriented to avoiding errors, but if you are sure that this wouldn't lead to an error you can simply cast the pointer to const char** .

    0 讨论(0)
  • 2020-11-30 13:52

    The reason char ** -> const char** is a "dangerous" conversion is the following code:

    const char immutable[] = "don't modify this";
    
    void get_immutable_str(const char **p) {
        *p = immutable;
        return;
    }
    
    int main() {
        char *ptr;
        get_immutable_str(&ptr); // <--- here is the dangerous conversion
        ptr[0] = 0;
    }
    

    The above code attempts to modify a non-modifiable object (the global array of const char), which is undefined behavior. There is no other candidate in this code for something to define as "bad", so const-safety dictates that the pointer conversion is bad.

    C does not forbid the conversion, but gcc warns you that it's bad. FYI, C++ does forbid the conversion, it has stricter const-safety than C.

    I would have used a string literal for the example, except that string literals in C are "dangerous" to begin with -- you're not allowed to modify them but they have type array-of-char rather than array-of-const char. This is for historical reasons.

    I thought a pointer to an address can always be casted to a const pointer

    A pointer-to-non-const-T can be converted to a pointer-to-const-T. char ** -> const char** isn't an example of that pattern, because if T is char * then const T is char * const, not const char * (at this point it's probably worthwhile not writing the const on the left any more: write char const * and you won't expect it to be the same as T const where T is char *).

    You can safely convert char ** to char * const *, and (for reasons that require a little more than just the simple rule) you can safely convert char ** to char const * const *.

    0 讨论(0)
  • 2020-11-30 13:55

    You cannot pass char ** into const char ** because the compiler cannot guarantee const correctness.

    Suppose you had the following code (and it compiled):

    void foo(const char **ppc, const char* pc)
    {
      *ppc = pc; // Assign const char* to const char*
    }
    
    void bar()
    {
      const char c = 'x';
      char* pc;
    
      foo(&pc, &c); // Illegal; converting const char* to const char**. Will set p == &c
      *pc = 'X';    // Ooops! That changed c.
    }
    

    See here for the same example without the function calls.

    0 讨论(0)
  • 2020-11-30 14:07

    The key is that not the pointer is const. To declare a const pointer, use char *const ptr; or to declare a const pointer to a const pointer, char *const *const ptr;. const char **ptr is a pointer to pointer to const char.

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