-1

im realy confused about const char * and char *. I know in char * when we want to modify the content, we need to do something like this

const char * temp = "Hello world";
char * str = new char[strlen(temp) + 1];
memcpy(str, temp, strlen(temp));
str[strlen(temp) + 1] = '\0';

and if we want to use something like this

char * str = "xxx";
char * str2 = "xts";
str = str2;

we get compiler warning. it's ok I know when i want to change char * I have to use something memory copy. but about const char * im realy confused. in const char * I can use this

const char * str = "Hello";
const char * str2 = "World";
str = str2; // and now str is Hello

and I have no compiler error ! why ? why we use memory copy when is not const and in const we only use equal operator ! and done !... how possible? is it ok to just use equal in const? no problem happen later?

JamesAlb
  • 263
  • 1
  • 3
  • 7
  • What specific compiler warning did you get when you did `char * str = "xxx"; char * str2 = "xts"; str = str2;`? – John Zwinck Jul 03 '17 at 14:47
  • 1
    this may help a bit: https://stackoverflow.com/questions/890535/what-is-the-difference-between-char-const-and-const-char the pointer is NOT constant so you can change what it points to but the value it points to is constant so you cannot change it. – Rob Jul 03 '17 at 14:48
  • 1
    warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings] – JamesAlb Jul 03 '17 at 14:50
  • Be careful to distinguish between a **pointer** and **what it points at**. Modifying the contents of a `char*` is simple: just assign a new value to it. This question is about modifying the contents of an array that a pointer points at, and that's a rather different subject. – Pete Becker Jul 03 '17 at 14:54
  • Beware that `str = str2` is changing *which* string `str` points to, it does not modify the value of the string it is pointing to in any way. – François Andrieux Jul 03 '17 at 14:54
  • What if you try `str[5]='!'` on the const char version? – doctorlove Jul 03 '17 at 14:54
  • 2
    Don't use `memcpy` here. Use `strcpy`. – Pete Becker Jul 03 '17 at 14:54
  • 2
    Use std::string. –  Jul 03 '17 at 14:57
  • You don't do either of these in C++. Not sure where you learnt this. – Lightness Races in Orbit Jul 03 '17 at 16:08

4 Answers4

1

This is a confusing hangover from the days of early C. Early C didn't have const, so string literals were "char *". They remained char * to avoid breaking old code, but they became non-modifiable, so const char * in all but name. So modern C++ either warns or gives an error (to be strictly conforming) when the const is omitted.

Your memcpy missed the trailing nul byte, incidentally. Use strcpy() to copy a string, that's the right function with the right name. You can create a string in read/write memory by use of the

char rwstring[] = "I am writeable";

syntax.

Malcolm McLean
  • 6,258
  • 1
  • 17
  • 18
1

As other answers say, you should distinguish pointers and bytes they point to.

Both types of pointers, char * and const char *, can be changed, that is, "redirected" to point to different bytes. However, if you want to change the bytes (characters) of the strings, you cannot use const char *.

So, if you have string literals "Hello" and "World" in your program, you can assign them to pointers, and printing the pointer will print the corresponding literal. However, to do anything non-trivial (e.g. change Hello to HELLO), you will need non-const pointers.

Another example: with some pointer manipulation, you can remove leading bytes from a string literal:

const char* str = "Hello";
std::cout << str; // Hello
str = str + 2;
std::cout << str; // llo

However, if you want to extract a substring, or do any other transformation on a string, you should reallocate it, and for that you need a non-const pointer.


BTW since you are using C++, you can use std::string, which makes it easier to work with strings. It reallocates strings without your intervention:

#include <string>
std::string str("Hello");
str = str.substr(1, 3);
std::cout << str; // ell
anatolyg
  • 26,506
  • 9
  • 60
  • 134
0

That is cause your variables are just a pointers *. You're not modifiying their contents, but where they are pointing to.

char * a = "asd";
char * b = "qwe";
a = b; 

now you threw away the contents of a. Now a and b points to the same place. If you modify one, both are modified.

In other words. Pointers are never constants (mostly). your const predicate in a pointer variable does not means nothing to the pointer.

The real difference is that the pointer (that is not const) is pointing to a const variable. and when you change the pointer it will be point to ANOTHER NEW const variable. That is why const has no effect on simple pointers.

Note: You can achieve different behaviours with pointers and const with more complex scenario. But with simple as it, it mostly has no effect.

Daniel Santos
  • 14,328
  • 21
  • 91
  • 174
0

Citing Malcolm McLean:

This is a confusing hangover from the days of early C. Early C didn't have const, so string literals were "char *". They remained char * to avoid breaking old code, but they became non-modifiable, so const char * in all but name.

Actually, string literals are not pointers, but arrays, this is why sizeof("hello world") works as a charm (yields 12, the terminating null character is included, in contrast to strlen...). Apart from this small detail, above statement is correct for good old C even in these days.

In C++, though, string literals have been arrays of constant characters (char const[]) right from the start:

C++ standard, 5.13.5.8:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration.

(Emphasised by me.) In general, you are not allowed to assign pointer to const to pointer to non-const:

char const* s = "hello";
char ss = s;

This will fail to compile. Assigning string literals to pointer to non-const should normally fail, too, as the standard explicitly states in C.1.1, subclause 5.13.5:

Change: String literals made const. The type of a string literal is changed from “array of char” to “array of const char”. [...]

char* p = "abc"; // valid in C, invalid in C++

Still, string literal assignement to pointer to non-const is commonly accepted by compilers (as an extension!), probably to retain compatibility to C. As this is, according to the standard, invalid, the compiler yields a warning, at least...

Aconcagua
  • 24,880
  • 4
  • 34
  • 59