What does const pointer mean???

Pages: 12
Feb 3, 2021 at 2:07pm
I do not understand what a const pointer means.
A pointer represents an address in the memory.

what does the code " const char * c = "sample text";" means?

since "sample text" is a content not an address.

Any reply would be appreciated.
Thanks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// const_cast
#include <iostream>
using namespace std;

void print (char * str)
{
  cout << str << '\n';
}

int main () {
  const char * c = "sample text";
  print ( const_cast<char *> (c) );
  return 0;
}
Feb 3, 2021 at 2:29pm
const char* c means that the data pointed to by the pointer c is const and can't be changed. The pointer can be changed to point elsewhere.

Not to be confused with:

char * const c

where c is a const pointer to the data - where the contents of the data can be changed but the value of the pointer (c) can not.

There is also

const char * const c

where both the data pointed to by c and the pointer itself are const and can't be changed.

Note that const char can also be written as char const with the same meaning.

When reading pointer types, it is usually helpful to read them from right to left.

char const * - pointer to const char
char * const - const pointer to char
char const * const - const pointer to const char
Feb 3, 2021 at 3:05pm
That is a naughty example. The "sample text" is a string literal constant. Those bytes will be in a memory area that must never be written to.
Your 'c' and 'str' are automatic variables and their content is stored in stack memory. That can be written to.

When you qualify a variable with const qualifier you ask the compiler to shout a warning, if you (accidentally) try to modify the value of that variable later in the code.


Your example first correctly says that whatever the 'c' points to shall not be modified.
However, on the next step you explicitly discard that safe-guard (with const_cast).
Luckily, you don't attempt to modify the memory pointed to by 'str'.


Earlier standard did allow pointing to string literal constants without the 'const'.
Note that char * c = "sample text"; now yields:
 In function 'int main()':
11:14: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

Old library functions (which do not modify via pointer) lack the const on their parameter list as it was not required. Hence,
1
2
  const char * c = "sample text";
  print ( c ); // error 

 In function 'int main()':
12:13: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]

Your example shows how to call such function (if you really must).


Pointer has a value, like any variable. That value is a memory address.
If pointer is const, then you cannot change the value. You cannot change where the pointer points to.

Pointer points to some memory area. When you dereference pointer, you access the value in that memory.
1
2
3
4
5
6
7
char line[] = "sample text"; // array 'line' is in stack and contains text
const char * c = line + 2; // pointer c points to 'm' in "mple text"
++c; // we can modify the pointer. Now it points to 'p' in "ple text"
*c = 'a'; // error: cannot assign to const memory
char * str = const_cast<char*>( c ); // str points to 'p' too.
*str = 'a'; // ok. modifying element of array 'line' is fine
// line now contains "samale text" 
Feb 3, 2021 at 5:22pm
> char * c = "sample text"; now yields: warning

It is an error in standard C++. http://coliru.stacked-crooked.com/a/11fd9535bec0d12e
Feb 3, 2021 at 5:46pm
My bad, did use cpp.sh's output, which is still limited to C++14.
Feb 3, 2021 at 5:54pm
It has been an error from C++11 onwards.
the clang++ diagnostic actually mentions C++11:
error: ISO C++11 does not allow conversion from string literal to 'char *'
Feb 3, 2021 at 7:12pm
It is an error in standard C++.

Weird how C/C++ allows so many implicit conversions, but this one is disallowed.

It isn't just clang, MSVC and MinGW has the error as well. Neither as informative as clang.

Maybe I'm misunderstanding what you mean when you say "[i]t is an error in standard C++." Is this happening according to the standard?

If it is "chapter and verse" in the standard, then my understanding needs some revision.
Feb 3, 2021 at 7:38pm
> it is an error in standard C++." Is this happening according to the standard?

There is no implicit conversion from const T* to T* : this has always been so in C++

C++11 specified that a string literal is an array of const character type. It is so, since then: https://eel.is/c++draft/lex.string#1
Feb 3, 2021 at 7:45pm
In C++ it says, "A narrow string literal has type “array of n const char”".
Thus, given that, it's the same reason that:
1
2
3
4
5
int main()
{
    const int arr[] = {3, 1, 4};
    int* ptr = arr;
}
does not compile.
Last edited on Feb 3, 2021 at 7:46pm
Feb 4, 2021 at 10:32am
Fascinating, GCC does merely warn:
1
2
3
4
int main()
{
    char * c = "sample text";
}

g++ (GCC) 8.3.1 20191121 (Red Hat 8.3.1-5) and g++ (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2):
$ g++ con.cpp  # default: -std=gnu++14
con.cpp: In function ‘int main()’:
con.cpp:3:16: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]

$ g++ -std=c++17 con.cpp 
con.cpp: In function ‘int main()’:
con.cpp:3:16: warning: ISO C++ forbids converting a string constant to ‘char*’ [-Wwrite-strings]

Feb 4, 2021 at 10:36am
Isn't it illegal in c++ but legal in c?
Feb 4, 2021 at 10:42am
"const char * c = "sample text";"
why it is not
"const char * c =& "sample text";"

since "sample text"is a content not an address, why "sample text" can be assigned to a pointer?
Feb 4, 2021 at 10:45am
> GCC does merely warn

To make the GNU compiler conform to standard C++, add -pedantic-errors in addition to -std=c++17.

With that, g++ would spit out:
main.cpp:4:16: error: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
    4 |     char * c = "sample text";
      |                ^~~~~~~~~~~~~

http://coliru.stacked-crooked.com/a/11fd9535bec0d12e
Feb 4, 2021 at 10:53am
The "sample text" initializes an unnamed array (where-ever literal constants are stored).
1
2
3
4
const char * c = "sample text";
// is kind of
const char literal[] = "sample text";
const char * c = literal;

There is implicit conversion from array to address of its first element.
Feb 4, 2021 at 11:12am
since "sample text"is a content not an address,


It is an address to some where in memory where the complier has located the text. A string literal is a pointer to memory of type const char. As the compiler can place the text in any convenient memory area - including the compiled code and RO memory - the contents of the string literal shouldn't be changed. Hence the requirement for the const char* type.

If the contents are required to be changed, then use

 
char ca[] {"sample text"};


the address of ca will probably be on the stack and the contents can be changed. This memory is initialised with the values "sample txt".

Note the difference between :

1
2
const char* c {"sample text"};
char ca[] {"sample text"};


ca can also be const qualified if required.

c is often defined as:

 
const char* const c {"sample text"};


where the data can't be changed and the value of the pointer c can't be changed either. Note that as ca is defined as an array, it's value can't be changed.
Last edited on Feb 4, 2021 at 12:09pm
Feb 4, 2021 at 11:16am
> A string literal is a pointer to memory of type char.

No. The type of a (narrow) string literal is 'array of N const char'; the array object has static storage duration.
Feb 4, 2021 at 12:09pm
1
2
3
4
5
6
7
8
#include <iostream>

int main()
{
	auto c {"qwerty"};

	std::cout << typeid(c).name() << '\n';
}


displays:


char const * __ptr64

Feb 4, 2021 at 12:30pm
That is the type of the pointer c, not the type of the string literal.

cpp.sh:
typeid(c).name()
St16initializer_listIPKcE

typeid("qwerty").name()
A7_c
Last edited on Feb 4, 2021 at 12:33pm
Feb 4, 2021 at 12:36pm
> displays: char const * __ptr64

So, there is an implicit array to pointer conversion. What else is new?

Without forcing the conversion:

1
2
3
4
5
6
7
8
9
#include <iostream>
#include <type_traits>

int main()
{
	auto& c {"qwerty"};

	std::cout << typeid(c).name() << '\n'; // array of 7 const char
}


http://coliru.stacked-crooked.com/a/1373d62e925e5a54
https://rextester.com/VKC79074
Feb 4, 2021 at 1:17pm
string literal is 'array of N const char'


Well I used C from about 1983 onwards till the late 1990's and used C++ continuously since 1992 - and I never realised that! I knew about the implicit array to pointer conversion but always thought that a string literal was a const char *. Well, this shows that you're never too old to learn!

@JLBorges - thanks for the correction! Is this the same in C?
Pages: 12