76

Can someone explain why this works with the pointer:

char * str1;

str1 = "Hello1";

str1 = "new string";

// but not this
char str2 [] = "hello";
str2 = "four";

// or this
char str3 [];
str3 = "hello";
str3 = "hello";
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
nick
  • 1,147
  • 1
  • 11
  • 12
  • 2
    [This question](http://stackoverflow.com/questions/164194) covers the same ground, just worded differently. I'm not sure if this is duplicate enough to close, but answers there do apply. – Tim Post Jul 24 '11 at 03:17
  • 6
    @Tim Post: The alleged duplicate question and its answer are IMO unrelated to this question because this one asks compile-time things, the other one asks runtime things – Armen Tsirunyan Jul 24 '11 at 10:48

5 Answers5

92

Why it works with pointers:
When you say char * str1 in C, you are allocating a pointer in the memory. When you write str1 = "Hello";, you are creating a string literal in memory and making the pointer point to it. When you create another string literal "new string" and assign it to str1, all you are doing is changing where the pointer points.

Why it doesn't work with arrays:
When you say char str2 [] = "Hello", you are creating a string literal and putting it in the array during its definition. It is ok to not give a size, as the array calculates it and appends a '\0' to it. You cannot reassign anything to that array without resizing it. That is why str2 = "four" will not work.

In case of str3, it is the same case. You haven't defined the size of the array in the definition, so it calculated its size to be 0. You cannot assign anything new without resizing the array.

Stefan van den Akker
  • 6,661
  • 7
  • 48
  • 63
tryurbest
  • 1,419
  • 1
  • 12
  • 22
  • Cheers, TryUrBest. Most C books I've looked at make a really big deal out of strings, pointers and arrays. In the case of str1 (the pointer) is that the way to do it? Stop worrying about "am I doing it 100% correct" and just make pointers to strings and use them as I did above? You said, that the first method moves the pointer, is the orig. data destroyed then, or is it a leak? – nick Jul 24 '11 at 06:03
  • @tryurbest: may I add further a question? in case using char* str="some string", is this string considered to be a fixed size string. If later on, this pointer is processed to add more string. Will that generate a memory access violation? Thank you! actually, I've tested it and see the error. But I'm not sure about the part "fixed size string" or "constant string" overthere – TSL_ Nov 29 '14 at 03:08
  • 3
    What happens to the old string "Hello". Does this be there is memory and contribute to memory leak? Or that is automatically released? – Jon Wheelock Oct 11 '15 at 02:05
  • 1
    According to K. N. King, in your second example char str2 [] = "Hello", although "Hello" appears to be a string literal, it's not. Instead, C views it as an abbreviation for an array initializer. – ilstam Jun 17 '17 at 19:24
24

An array and a pointer are different things, that's why. You can assign to a pointer, but you can't assign to an array. A special exception is made for initialization of char arrays with string literals.

char a[] = "Hello"; //initialize a char array with string literal. Special case, OK
char* p = "Hello"; //initializa a pointer with an array(which gets converted to pointer)
p = "My";   //assign pointer to point to another value. OK
a = "My";   //error, arrays cannot be assigned to. Use `strcpy`

String literals (such as "Hello") have type char[N] where N is number of characters (including the terminating '\0'). An array can be converted to a pointer to its first element, but arrays and pointers are not the same thing, whatever some bad books or teachers may say.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 2
    Don't forget `const` as an issue here. – Puppy Jul 23 '11 at 21:28
  • 4
    @DeadMG: AFAIK in C string literals are not `const char [N]`. They are `char [N]`. That's why we (used to) have the implicit conversion to `char*` of string literals in C++. Am I wrong? – Armen Tsirunyan Jul 23 '11 at 21:30
  • @Armen: No, they are officially not `const char[N]`, but in reality, they very often are. Most compilers put string literals in read-only memory. That means the user should generally not try to do `*p = 'A';`. – Rudy Velthuis Jul 23 '11 at 21:39
  • 3
    @Rudy: Regardless of where the compiler keeps a string literal, doing `*p = 'A'` has undefined behavior, which IMO is irrelevant to the OP's question. But the type of a string literal is (unfortunately) just `char[N]` in C. – Armen Tsirunyan Jul 23 '11 at 21:44
  • OK Guys, thanks. Armen made a really good point. I have read that pointers and arrays are basically the same. – nick Jul 24 '11 at 05:50
  • For example, the arr in arr[20] can be used as a pointer to the first element of the array.This works, I use it, but is it flakey? – nick Jul 24 '11 at 05:57
  • @Armen - sorry, forgot the @ on your name. – nick Jul 24 '11 at 07:07
  • @nick. As an `rvalue`, an array is almost always converted to a pointer, so you can use it as a pointer. But as an `lvalue` there is difference - for example in the case of your question – Armen Tsirunyan Jul 24 '11 at 07:10
7

Put simply, because an array is not a first-class object in C/C++. The only way to assign to an array is to use str(n)cpy or memcpy.

While an array collapses into a pointer when passed to a function, it is not possible to assign to an array, except at compile-time as initialisation.

Julian
  • 2,021
  • 16
  • 21
5

It is simply because, when you write this code:

char str2 [] = "hello";

or even:

int arr[] = {1,2,4,4,5};

it creates str2 or arr as a constant pointer. That's why you can not reassign any other values to these pointers while in later case you are creating a normal pointer and you can assign anything to it.

Chris Krycho
  • 3,125
  • 1
  • 23
  • 35
Sawan
  • 236
  • 3
  • 12
5

The case with pointers It works because when you are assigning like str1="Hello" , You are actually creating a string literal named hello allocating it somewhere in the memory , and assigning the address of first character of the literal to the pointer , and as the pointer is not constant you can assign it again with different addresses. And one more important point to note is that the string literal created are in read only memory.

The case with character array You can assign it a string literal while initialisation as that is supported by the language . And dont confuse assignment with initialisation. While assignment , since its an character array you have to change value character by character ,You are trying to address the first address of the string literal to the first character of the array ( the name of the array return the address of first element of the array).And this clearly is not right as the first element is not pointer , it cant store address.

parth_07
  • 1,322
  • 16
  • 22