-2

PART 1

I have 2 strings and they are defined in following ways-

char s1[] = "foo";
char *s2 = "foo";

When I try to change a character of these strings, say, the 2nd character -

char s1[1] = 'x';
char s2[1] = 'x';

the character in string s1 changes, but changing the character in string s2 gives me this error - Segmentation fault (core dumped).

Why is it so?

Why am I unable to change the character of the string which is defined in the other way?


PART 2

Strings (they are array of characters, right?) can be initialized using - char *s = "foo" but why does compiler gives warnings when I try to initialize arrays of different type using the same thing like int *arr = {1, 2, 3}?

foo.c: In function ‘main’:
foo.c:5:5: warning: initialization makes pointer from integer without a cast [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]
foo.c:5:5: warning: excess elements in scalar initializer [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]
foo.c:5:5: warning: excess elements in scalar initializer [enabled by default]
foo.c:5:5: warning: (near initialization for ‘foo’) [enabled by default]

NOTE: My compiler is GCC.

ShuklaSannidhya
  • 8,572
  • 9
  • 32
  • 45
  • 1
    **`s1` is an array** (with 4 elements); **`s2` is a pointer** (to the first element of an (un-modifiable) array with 4 elements). A "string" is an array where one of it's elements is `'\0'`. Read the [comp.lang.c FAQ](http://c-faq.com/), starting with section 6. – pmg May 19 '13 at 15:53
  • @KingsIndian There is a **PART 2** also. – ShuklaSannidhya May 19 '13 at 15:57
  • @pmg It doesn't have to be "un-modifiable". Only modifying it is UB. There's a subtle difference. – P.P May 19 '13 at 16:11
  • @KingsIndian: I mean "un-modifiable under penalty of UB". The point being that, unlike what some people thing, **in C**, a string literal is not a constant: it is of type `char [N] /* with N large enough for all elements and the nul byte */`, not `const char[N]`. Note I didn't say "const" (or "constant") for that reason :) – pmg May 19 '13 at 16:18

1 Answers1

4

The first one is a string that is an array of characters, filled with the characters in the string "foo", the second one is a pointer to a constant with the value "foo". Since the second one is constant, it isn't allowed to modify it.

And no, you can't initialize a pointer to set of values - because the pointer has no actual memory to store the values assigned to it. You need to either make it point to another array:

int foox[3] = { 1, 2, 3 };
int *foo = foox;

or you need to allocate some memory, and then store the values:

int *foo = malloc(sizeof(int) * 3);

foo[0] = 1; 
foo[1] = 2; 
foo[2] = 3; 
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • So can I call such strings immutable? – ShuklaSannidhya May 19 '13 at 16:02
  • 3
    That standard says that it is "undefined behaviour" to write to them - it's entirely possible that you can write to such a string in some circumstances [e.g. using Turbo C++, you probably could, because it generates code for DOS, which doesn't have any ability to write-protect memory, so there's nothing to stop you from writing to the string - or overwriting the code you are currently executing, should you write code that does that, intentionally or otherwise]. – Mats Petersson May 19 '13 at 16:08