Categories
c char constants string

What is the difference between char s[] and char *s?

564

In C, one can use a string literal in a declaration like this:

char s[] = "hello";

or like this:

char *s = "hello";

So what is the difference? I want to know what actually happens in terms of storage duration, both at compile and run time.

3

  • 12

  • 12

    char *s=”hello”, here s can point any another string at run time I mean it is not constant pointer you can assign another value at run time p = “Nishant”, while s[] here s is constant pointer….it can’t be reasign another string but we can assign another character value at s[index].

    May 16, 2012 at 14:49

  • @NishantYou meant ..you can assign another value at run time s = “Nishant”, while s[] … Did you? Otherwise, it is a little bit confusing in the context.

    – Yifangt

    Mar 4 at 4:26


606

The difference here is that

char *s = "Hello world";

will place "Hello world" in the read-only parts of the memory, and making s a pointer to that makes any writing operation on this memory illegal.

While doing:

char s[] = "Hello world";

puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. Thus making

s[0] = 'J';

legal.

18

  • 30

    The literal string "Hello world" is in “read-only parts of the memory” in both examples. The example with the array points there, the example with the array copies the characters to the array elements.

    – pmg

    Nov 9, 2009 at 22:42

  • 36

    pmg: In the second case the literal string does not necessarily exist in memory as a single contiguous object at all – it’s just an initialiser, the compiler could quite resonably emit a series of “load immediate byte” instructions that contain the character values embedded within them.

    – caf

    Nov 9, 2009 at 22:46

  • 14

    The char array example does not necessarily place the string on the stack – if it appears at file level, it will probably be in some kind of initialised data segment instead.

    – caf

    Nov 9, 2009 at 22:47

  • 11

    I’d like to point out that char s = “xx” doesn’t have to be in read-only memory (some implementations have no MMUs, for example). The n1362 c1x draft simply states that modifying such an array causes undefined behavior. But +1 anyway, since relying on that behavior is a silly thing to do.

    – paxdiablo

    Nov 10, 2009 at 12:35

  • 3

    I get a clean compile on a file containing just char msg[] = "hello, world!"; the string ends up in the initialized data section. When declared char * const to end up in the read-only data section. gcc-4.5.3

    – gcbenison

    Apr 27, 2012 at 15:44

172

First off, in function arguments, they are exactly equivalent:

void foo(char *x);
void foo(char x[]); // exactly the same in all respects

In other contexts, char * allocates a pointer, while char [] allocates an array. Where does the string go in the former case, you ask? The compiler secretly allocates a static anonymous array to hold the string literal. So:

char *x = "Foo";
// is approximately equivalent to:
static const char __secret_anonymous_array[] = "Foo";
char *x = (char *) __secret_anonymous_array;

Note that you must not ever attempt to modify the contents of this anonymous array via this pointer; the effects are undefined (often meaning a crash):

x[1] = 'O'; // BAD. DON'T DO THIS.

Using the array syntax directly allocates it into new memory. Thus modification is safe:

char x[] = "Foo";
x[1] = 'O'; // No problem.

However the array only lives as long as its contaning scope, so if you do this in a function, don’t return or leak a pointer to this array – make a copy instead with strdup() or similar. If the array is allocated in global scope, of course, no problem.

0

    84

    This declaration:

    char s[] = "hello";
    

    Creates one object – a char array of size 6, called s, initialised with the values 'h', 'e', 'l', 'l', 'o', '\0'. Where this array is allocated in memory, and how long it lives for, depends on where the declaration appears. If the declaration is within a function, it will live until the end of the block that it is declared in, and almost certainly be allocated on the stack; if it’s outside a function, it will probably be stored within an “initialised data segment” that is loaded from the executable file into writeable memory when the program is run.

    On the other hand, this declaration:

    char *s ="hello";
    

    Creates two objects:

    • a read-only array of 6 chars containing the values 'h', 'e', 'l', 'l', 'o', '\0', which has no name and has static storage duration (meaning that it lives for the entire life of the program); and
    • a variable of type pointer-to-char, called s, which is initialised with the location of the first character in that unnamed, read-only array.

    The unnamed read-only array is typically located in the “text” segment of the program, which means it is loaded from disk into read-only memory, along with the code itself. The location of the s pointer variable in memory depends on where the declaration appears (just like in the first example).

    5

    • 1

      In both declaration for “hello” memory is allocated at comiple time ?.And another thing char *p = “hello” here “hello” is stored in text segment as you stated in your answer…and what about char s[] = “hello” will it also store first in text segment part and during run time it will copy in stack as Rickard has stated in there answer. please clarify this point.

      May 16, 2012 at 15:00

    • 2

      @Nishant: In the char s[] = "hello" case, the "hello" is just an initialiser telling the compiler how the array should be initialised. It may or may not result in a corresponding string in the text segment – for example, if s has static storage duration then it is likely that the only instance of "hello" will be in the initialised data segment – the object s itself. Even if s has automatic storage duration, it can be initialised by a sequence of literal stores rather than a copy (eg. movl $1819043176, -6(%ebp); movw $111, -2(%ebp)).

      – caf

      May 17, 2012 at 1:28

    • More precisely, GCC 4.8 puts it into .rodata, which the linker script then dumps into the same segment as .text. See my answer.

      Jun 5, 2015 at 7:33


    • @caf In the first answer by Rickard, It’s written that char s[] = "Hello world"; puts the literal string in read-only memory and copies the string to newly allocated memory on the stack. But, your answer only speaks about the literal string put in read-only memory and skips the second part of the sentence which says: copies the string to newly allocated memory on the stack. So, is your answer incomplete for not specifying the second part?

      Jan 7, 2019 at 10:11

    • 1

      @AjaySinghNegi: As I’ve stated in other comments (to this answer, and Rickard’s answer), the string in char s[] = "Hellow world"; is only an initializer and is not necessarily stored as a separate read-only copy at all. If s has static storage duration then the only copy of the string is likely to be in a read-write segment at the location of s, and even if not then the compiler may choose to initialize the array with load-immediate instructions or similar rather than copying from a read-only string. The point is that in this case, the initializer string itself has no runtime presence.

      – caf

      Jan 8, 2019 at 9:39