In C, can I initialize a string in a pointer declaration the same way I can initialize a string in a char array declaration?
Asked Answered
L

3

16

Do these two lines of code achieve the same result? If I had these lines in a function, is the string stored on the stack in both cases? Is there a strong reason why I should use one over the other, aside from not needing to declare the null terminator in the first line of code?

char  s[] = "string";
char* s   = "string\0";
Larrabee answered 29/10, 2010 at 11:28 Comment(3)
Just for information, you don't need the \0 in the second example. When using double quotes, \0 is always inserted in the array.Captivate
And just for the vocabulary, what you are talking about are not assignments, but declarations with initializers. They obey different rules. E.g your first statement would not be permitted as an assignment, you can't assign arrays.Wyler
possible duplicate of C: differences between pointer and arrayWyler
B
31

No, those two lines do not achieve the same result.

char s[] = "string" results in a modifiable array of 7 bytes, which is initially filled with the content 's' 't' 'r' 'i' 'n' 'g' '\0' (all copied over at runtime from the string-literal).

char *s = "string" results in a pointer to some read-only memory containing the string-literal "string".

If you want to modify the contents of your string, then the first is the only way to go. If you only need read-only access to a string, then the second one will be slightly faster because the string does not have to be copied.


In both cases, there is no need to specify a null terminator in the string literal. The compiler will take care of that for you when it encounters the closing ".

Br answered 29/10, 2010 at 11:41 Comment(6)
Also, the second one is only allowed for horrible legacy reasons. You should use const char *s = "string";Innocuous
@Steve: For C++ I would completely agree with you. For C, I tend to give a bit more leeway, because in practice there are too many ways that the const gets into your way. (That is also known as const-poisoning)Br
If I'm using dodgy libraries, I agree with you (sometimes). If the code is under my control then I fix it so that const doesn't get in my way. The alternative is to take copies of strings that have to be passed as non-const parameters to dodgy APIs. Sometimes that's do-able, for instance if the string being passed is a literal defined close to the call, or as a global, then just use the first of the two options above. Other times it's a PITA, in which case you could either take the hit of strdup, or cast away const (which is "unsafe", but then you're already using an "unsafe" API).Innocuous
The second version is very useful for arrays of constant strings of different lengths or inclusion of constant strings within structures (though I tend to use const in the declaration if I can).Garald
Why can't we modify the second one? I have basic understanding of stack, so please be gentle.Poodle
@KaranSingh: You can't modify the second one because the C language says so. Making string-literals read-only makes it possible for the compiler to use a single piece of memory for multiple identical literals.Br
V
4

The difference between these two:

char a[] = "string";
char* b = "string";

is that a is actually a static array on stack, while b is a pointer to a constant. You can modify the content of a, but not b.

Vinny answered 29/10, 2010 at 11:42 Comment(0)
C
4

In addition to the other answers I will try to explain why you cannot modify the *s variable later on the program flow.

Conceptually when a program is loaded in memory it has 3 areas (segments):

  • code segment: the text of your program is stored here (it is a read-only area)
  • data segment: contains any global or static variables which have a pre-defined value and can be modified
  • stack segment: here are loaded the functions as they are called. The set of values (a stack frame) pushed on the stack for every function call which contains the return address off the function and the local variables.

In your case the s[] variable is a local variable (array), in the main() function, which is initialized with the value "string" . Thus, it is stored on the stack and can be modified.

The *s variable is a pointer which points to the address of "string\0", a constant located in the code segment. Being a read-only area, you cannot modify it's contents.

Crackbrain answered 26/6, 2017 at 22:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.