const pointer assign to a pointer

56,820

There is difference between constant pointer and pointer to constant. Constant pointer is a pointer (a number - memory address) that cannot be changed - it always point to the same object given via initialization:

int * const const_pointer = &some_int_var; // will be always pointing to this var
const_pointer = &some_other_var; // illegal - cannot change the pointer
*const_pointer = 2; // legal, the pointer is a pointer to non-const

Pointer to constant is a pointer whose pointed value cannot be changed:

const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it
*pointer = 2; // illegal, pointed value cannot be changed

You can always assign constant to variable i.e. const pointer to non-const pointer (a). You can cast pointer to non-const to a pointer to const (b). But you cannot cast pointer to const to a pointer to non-const (c):

int * pointer;
int * const const_pointer = &var;
const int * pointer_to_const;

/* a */
pointer = const_pointer; // OK, no cast (same type)

/* b */
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*'

/* c */
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*'

[EDIT] Below, this is not standard c++. However, this is common.[/EDIT]
String literal

"Hello"

is converted to constant pointer to const (const char * const):

char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*')
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant

In above examples the second is your case. You tried to initialize pointer-to-non-const with a pointer-to-const when passing string literal as argument of your function. No matter if these pointers are constants or not, it's matter what do they point to.

Summary:
1) If you cast a pointer of some type to a pointer of another type, you cannot cast pointer-to-const to pointer-to-non-const.
2) If you have constant pointer, the same rules applies as to other constants - you can assign a constant to a variable but you cannot assign a variable to a constant (except initializing it).

// EDIT
As GMan pointed out, the C++98 standard (§4.2/2) allows to implicitly cast string literals (which are constant char arrays) to a non-const char pointer. This is because of backward compatibility (in C language there are no constants).

Of course such a conversion can lead to mistakes and compilers will violate the rule and show an error. However, GCC in compatibility mode shows only a warning.

Share:
56,820
Tony The Lion
Author by

Tony The Lion

#disgusted

Updated on July 09, 2022

Comments

  • Tony The Lion
    Tony The Lion almost 2 years

    Why can I not do this:

    char* p = new char[10];
    
    void SetString(char * const str)
    {
        p = str;
    }
    
    
    SetString("Hello");
    

    I have a const pointer to a char, why can I not assign the const pointer to another pointer?

    It just seems illogical, as by assigning it to another pointer, you are not essentially violating the const-ness of the char pointer. Or are you?

    EDIT: When I compile this it says "error C2440: '=' : cannot convert from 'char *const *__w64 ' to 'char *'"

    (I'm attempting to understand a concept from a book I'm reading. Just cannot get the code to compile.

    CODE:

    int _tmain(int argc, _TCHAR* argv[])
    {
    
        MyString *strg = new MyString(10);
        strg->SetString("Hello, ");
    
        MyString *secondstr = new MyString(7);
        secondstr->SetString("Tony");
    
        strg->concat(*secondstr, *strg);
    
    }
    

    CPP FILE:

    #include "MyStringClass.h"
    #include <string.h>
    #include "stdafx.h"
    
    #include "MyStringClass.h"
    
    void MyString::concat(MyString& a, MyString& b)
    {
        len = a.len + b.len;
        s = new char[len + 1];
        strcpy(s, a.s);
        strcat(s, b.s);
        delete [] s; 
    
    }
    
    void MyString::SetString(char * const str)
    {
        s = str;
    }
    
    MyString::MyString(int n)
    {
        s = new char[n+1];
        s[n+1] = '\0';
        len = n;
    }
    

    HEADER FILE:

    #include <string.h>
    #include <stdio.h>
    
    class MyString
    {
    private:
        char* s;
        int len;
    public:
        MyString(int n = 80);
    
        void SetString (char * const str);
    
        void concat (MyString& a, MyString& b);
    };