266

What's the difference between

char* name

which points to a constant string literal, and

const char* name
zergius
  • 344
  • 1
  • 6
  • 12
Iceman
  • 4,202
  • 7
  • 26
  • 39
  • what do you mean by "**constant** string literal" in C (not C++) – gbulmer Mar 23 '12 at 04:49
  • 1
    ... char *name can be made to point to a constant string literal – Iceman Mar 23 '12 at 15:15
  • the constant in "constant string literal" is redundant, since all string literals are in theory constant entities. It's the contents of the variable that can be made either constant or mutable. The "const" declaration simply will throw a compile time error if you try to change the contents of the character pointed to by "name" – Cupcake Jul 31 '16 at 04:49
  • 1
    Simple: "char *name" name is a pointer to char, i.e. both can be change here. "const char *name" name is a pointer to const char i.e. pointer can change but not char. – akD Apr 27 '17 at 06:20
  • 2
    Read these things from right to left. – JP Zhang May 24 '20 at 16:14

9 Answers9

550

char* is a mutable pointer to a mutable character/string.

const char* is a mutable pointer to an immutable character/string. You cannot change the contents of the location(s) this pointer points to. Also, compilers are required to give error messages when you try to do so. For the same reason, conversion from const char * to char* is deprecated.

char* const is an immutable pointer (it cannot point to any other location) but the contents of location at which it points are mutable.

const char* const is an immutable pointer to an immutable character/string.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
ankit.karwasra
  • 5,626
  • 2
  • 13
  • 7
  • 4
    Confusion can get cleared up with the use of a variable after the statements mentioned above and by giving reference to that variable. – ankit.karwasra Oct 08 '13 at 09:16
  • 4
    @ankit.karwasra, You missed out one more: `char const * ` – Pacerier May 13 '15 at 03:27
  • I supose two options with mutable character/string are highly dangerous, since you could do a segmetation fault memory, and if you are really smart you could hack the computer. That is why compilers always shown warnings in those implementations I think – Daniel N. May 15 '15 at 04:22
  • 3
    Won't mutating `char *` give segmentation fault while running? – Divyanshu Maithani Feb 21 '17 at 08:52
  • 1
    So I use `const` if I want the compiler to give error if I forgot and changed the data by mistake, right ? – Accountant م Apr 06 '19 at 22:12
  • Is there any way to assign one to the other and vice-versa? – asn Jul 08 '19 at 18:28
  • 7
    @DivyanshuMaithani It depends where `char *` is created. For example: `char *s = "A string"` puts `"A string"` in to the code section (RO memory) of your binary. Writing to this memory seg faults. But `char *s = malloc(sizeof(char) * 10)` allocates memory on the heap, and this memory section is writeable and hence doesn't seg fault on write. – d4rwel Apr 21 '20 at 12:39
46
char *name

You can change the char to which name points, and also the char at which it points.

const char* name

You can change the char to which name points, but you cannot modify the char at which it points.
correction: You can change the pointer, but not the char to which name points to (https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx, see "Examples"). In this case, the const specifier applies to char, not the asterisk.

According to the MSDN page and http://en.cppreference.com/w/cpp/language/declarations, the const before the * is part of the decl-specifier sequence, while the const after * is part of the declarator.
A declaration specifier sequence can be followed by multiple declarators, which is why const char * c1, c2 declares c1 as const char * and c2 as const char.

EDIT:

From the comments, your question seems to be asking about the difference between the two declarations when the pointer points to a string literal.

In that case, you should not modify the char to which name points, as it could result in Undefined Behavior. String literals may be allocated in read only memory regions (implementation defined) and an user program should not modify it in anyway. Any attempt to do so results in Undefined Behavior.

So the only difference in that case (of usage with string literals) is that the second declaration gives you a slight advantage. Compilers will usually give you a warning in case you attempt to modify the string literal in the second case.

Online Sample Example:

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

Output:

cc1: warnings being treated as errors
prog.c: In function ‘main’:
prog.c:9: error: passing argument 1 of ‘strcpy’ discards qualifiers from pointer target type

Notice the compiler warns for the second case but not for the first.

Emily Chen
  • 159
  • 1
  • 10
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • Thanks.. i was mixing with the constant string literal, which is defined as: char* name = "String Literal"; Changing "String Literal" is undefined.. – Iceman Mar 23 '12 at 04:20
  • @user1279782: Err, Wait! Are you talking about pointes pointing to string literals here? In that case You **should not** modify the char to which the `name` points in either case.It could result in UB. – Alok Save Mar 23 '12 at 04:24
  • Yes, that was the point. So in that case char* name and const char* name behave similar, right? – Iceman Mar 23 '12 at 04:28
  • @user1279782: I updated the answer to address your query. Hth. – Alok Save Mar 23 '12 at 04:42
  • 4
    This answer is either extremely ambiguous or just plain wrong. I would interpret "You cannot change the char to which name points, but You can modify the char at which it points." As not being able to modify the pointer itself, but being able to modify the memory location that it points to, which is incorrect: http://ideone.com/6lUY9s alternatively for pure C: http://ideone.com/x3PcTP – shroudednight Jan 04 '13 at 23:34
  • 1
    @shroudednight: You need to learn a little more about Undefined behaviors, and need to distinguish between: allowed and should not be done. :) – Alok Save Jan 05 '13 at 05:29
  • Please make the correction strcpy(str1,source); //Compiler issue a warning here. and Behavior is undefined. strcpy(str2,source); //Compiler issues a error – Devesh Agrawal Oct 28 '13 at 18:15
26
char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok
Afriza N. Arief
  • 7,696
  • 5
  • 47
  • 74
13

In neither case can you modify a string literal, regardless of whether the pointer to that string literal is declared as char * or const char *.

However, the difference is that if the pointer is const char * then the compiler must give a diagnostic if you attempt to modify the pointed-to value, but if the pointer is char * then it does not.

caf
  • 233,326
  • 40
  • 323
  • 462
  • 1
    "In neither case can you modify a string literal, regardless of whether ... [it] is declared as char * or const char *" I agree that the programmer should not try, but are you saying that every C compiler, on every platform will reject the code, arrange for the code to fail at run time, or something else? I believe, one file could have the definition and initialisation, and another file might contain `extern ... name` and have `*name = 'X';`. On 'proper operating system', that might fail, but on embedded systems, I'd expect it to do something platform/compiler specific. – gbulmer Mar 23 '12 at 04:44
  • @gbulmer: You cannot modify a string literal in a correct C program. What an incorrect C program which tries may result in is neither here nor there. – caf Mar 23 '12 at 05:27
  • @gbulmer: One useful definition is a program that doesn't break any constraints specified by the C language standard. In other words, a program that modifies a string literal is incorrect in the same way as one that dereferences a null pointer or performs a division by 0 is incorrect. – caf Mar 23 '12 at 14:26
  • caf - I thought that might be what you meant. Then "In neither case **can** you modify a string literal" seems to be over stating it. It would be accurate to say "In both cases the constraints specified by the C language standard have been broken, regardless.... It is not possible for the compiler or run time system to identify breaches of the standard in all cases." I assume the standard takes the position that the effect is undefined? – gbulmer Mar 23 '12 at 14:48
  • @gbulmer: Yes, the behaviour is undefined. I would also say that you cannot dereference a null pointer in a correct C program (regardless of the fact that it might not produce a harmful result on some specific implementations), and I don't think that this would be considered a controversial position. – caf Mar 24 '12 at 00:53
  • 1
    When a standard can't assert anything either way, I think defining behaviour as being 'undefined' seems to be exactly the right boundary and helpful. To assert the relation a 'correct C program' '**cannot** dereference a null pointer' sounds equivalent to proving the halting problem. But I don't mind. I wouldn't do it and expect to get away with it 'scott free' :-) – gbulmer Mar 24 '12 at 01:15
8

CASE 1:

char *str = "Hello";
str[0] = 'M'  //Warning may be issued by compiler, and will cause segmentation fault upon running the programme

The above sets str to point to the literal value "Hello" which is hard-coded in the program's binary image, which is flagged as read-only in memory, means any change in this String literal is illegal and that would throw segmentation faults.

CASE 2:

const char *str = "Hello";
str[0] = 'M'  //Compile time error

CASE 3:

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".
Dean P
  • 1,841
  • 23
  • 23
Mohit
  • 885
  • 9
  • 7
3

The question is what's the difference between

char *name

which points to a constant string literal, and

const char *cname

I.e. given

char *name = "foo";

and

const char *cname = "foo";

There is not much difference between the 2 and both can be seen as correct. Due to the long legacy of C code, the string literals have had a type of char[], not const char[], and there are lots of older code that likewise accept char * instead of const char *, even when they do not modify the arguments.

The principal difference of the 2 in general is that *cname or cname[n] will evaluate to lvalues of type const char, whereas *name or name[n] will evaluate to lvalues of type char, which are modifiable lvalues. A conforming compiler is required to produce a diagnostics message if target of the assignment is not a modifiable lvalue; it need not produce any warning on assignment to lvalues of type char:

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostic message

The compiler is not required to stop the compilation in either case; it is enough that it produces a warning for the assignment to cname[0]. The resulting program is not a correct program. The behaviour of the construct is undefined. It may crash, or even worse, it might not crash, and might change the string literal in memory.

2

The first you can actually change if you want to, the second you can't. Read up about const correctness (there's some nice guides about the difference). There is also char const * name where you can't repoint it.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
chikuba
  • 4,229
  • 6
  • 43
  • 75
1

I would add here that the latest compilers, VS 2022 for instance, do not allow char* to be initialized with a string literal. char* ptr = "Hello"; throws an error whilst const char* ptr = "Hello"; is legal.

1

Actually, char* name is not a pointer to a constant, but a pointer to a variable. You might be talking about this other question.

What is the difference between char * const and const char *?

Community
  • 1
  • 1
Jeff Wolski
  • 6,332
  • 6
  • 37
  • 69