C strings pointer vs. arrays [duplicate] - c

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Why is:
char *ptr = "Hello!"
different than:
char ptr[] = "Hello!"
Specifically, I don't see why you can use (*ptr)++ to change the value of 'H' in the array, but not the pointer.
Thanks!

You can (in general) use the expression (*ptr)++ to change the value that ptr points to when ptr is a pointer and not an array (ie., if ptr is declared as char* ptr).
However, in your first example:
char *ptr = "Hello!"
ptr is pointing to a literal string, and literal strings are not permitted to be modified (they may actually be stored in memory area which are not writable, such as ROM or memory pages marked as read-only).
In your second example,
char ptr[] = "Hello!";
The array is declared and the initialization actually copies the data in the string literal into the allocated array memory. That array memory is modifiable, so (*ptr)++ works.
Note: for your second declaration, the ptr identifier itself is an array identifier, not a pointer and is not an 'lvalue' so it can't be modified (even though it converts readily to a pointer in most situations). For example, the expression ++ptr would be invalid. I think this is the point that some other answers are trying to make.

When pointing to a string literal, you should not declare the chars to be modifiable, and some compilers will warn you for this:
char *ptr = "Hello!" /* WRONG, missing const! */
The reason is as noted by others that string literals may be stored in an immutable part of the program's memory.
The correct "annotation" for you is to make sure you have a pointer to constant char:
const char *ptr = "Hello!"
And now you see directly that you can't modify the text stored at the pointer.

Arrays automatically allocate space and they can't be relocated or resized while pointers are explicitly assigned to point to allocated space and can be relocated.
Array names are read only!

If You use a string literal "Hello!", the literal itself becomes an array of 7 characters and gets stored somewhere in a data memory. That memory may be read only.
The statement
char *ptr = "Hello!";
defines a pointer to char and initializes it, by storing the address of the beginning of the literal (that array of 7 characters mentioned earlier) in it. Changing contents of the memory pointed to by ptr is illegal.
The statement
char ptr[] = "Hello!";
defines a char array (char ptr[7]) and initializes it, by copying characters from the literal to the array. The array can be modified.

in C strings are arrays of characters.
A pointer is a variable that contains the memory location of another variable.
An array is a set of ordered data items.
when you put (*ptr)++ you are getting Segmentation Fault with the pointer.
Maybe you are adding 1 to the whole string (with the pointer), instead of adding 1 to the first character of the variable (with the array).

Related

Why does C allow a change to arr[0] and not to ptr[0] after passing them as arguments? [duplicate]

The following code receives seg fault on line 2:
char *str = "string";
str[0] = 'z'; // could be also written as *str = 'z'
printf("%s\n", str);
While this works perfectly well:
char str[] = "string";
str[0] = 'z';
printf("%s\n", str);
Tested with MSVC and GCC.
See the C FAQ, Question 1.32
Q: What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
A: A string literal (the formal term
for a double-quoted string in C
source) can be used in two slightly
different ways:
As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values
of the characters in that array (and,
if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters,
and this unnamed array may be stored
in read-only memory, and which
therefore cannot necessarily be
modified. In an expression context,
the array is converted at once to a
pointer, as usual (see section 6), so
the second declaration initializes p
to point to the unnamed array's first
element.
Some compilers have a switch
controlling whether string literals
are writable or not (for compiling old
code), and some may have options to
cause string literals to be formally
treated as arrays of const char (for
better error catching).
Normally, string literals are stored in read-only memory when the program is run. This is to prevent you from accidentally changing a string constant. In your first example, "string" is stored in read-only memory and *str points to the first character. The segfault happens when you try to change the first character to 'z'.
In the second example, the string "string" is copied by the compiler from its read-only home to the str[] array. Then changing the first character is permitted. You can check this by printing the address of each:
printf("%p", str);
Also, printing the size of str in the second example will show you that the compiler has allocated 7 bytes for it:
printf("%d", sizeof(str));
Most of these answers are correct, but just to add a little more clarity...
The "read only memory" that people are referring to is the text segment in ASM terms. It's the same place in memory where the instructions are loaded. This is read-only for obvious reasons like security. When you create a char* initialized to a string, the string data is compiled into the text segment and the program initializes the pointer to point into the text segment. So if you try to change it, kaboom. Segfault.
When written as an array, the compiler places the initialized string data in the data segment instead, which is the same place that your global variables and such live. This memory is mutable, since there are no instructions in the data segment. This time when the compiler initializes the character array (which is still just a char*) it's pointing into the data segment rather than the text segment, which you can safely alter at run-time.
Why do I get a segmentation fault when writing to a string?
C99 N1256 draft
There are two different uses of character string literals:
Initialize char[]:
char c[] = "abc";
This is "more magic", and described at 6.7.8/14 "Initialization":
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
So this is just a shortcut for:
char c[] = {'a', 'b', 'c', '\0'};
Like any other regular array, c can be modified.
Everywhere else: it generates an:
unnamed
array of char What is the type of string literals in C and C++?
with static storage
that gives UB if modified
So when you write:
char *c = "abc";
This is similar to:
/* __unnamed is magic because modifying it gives UB. */
static char __unnamed[] = "abc";
char *c = __unnamed;
Note the implicit cast from char[] to char *, which is always legal.
Then if you modify c[0], you also modify __unnamed, which is UB.
This is documented at 6.4.5 "String literals":
5 In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals. The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. For character string literals, the array elements have
type char, and are initialized with the individual bytes of the multibyte character
sequence [...]
6 It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
6.7.8/32 "Initialization" gives a direct example:
EXAMPLE 8: The declaration
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
GCC 4.8 x86-64 ELF implementation
Program:
#include <stdio.h>
int main(void) {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compile and decompile:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output contains:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Conclusion: GCC stores char* it in .rodata section, not in .text.
If we do the same for char[]:
char s[] = "abc";
we obtain:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
so it gets stored in the stack (relative to %rbp).
Note however that the default linker script puts .rodata and .text in the same segment, which has execute but no write permission. This can be observed with:
readelf -l a.out
which contains:
Section to Segment mapping:
Segment Sections...
02 .text .rodata
In the first code, "string" is a string constant, and string constants should never be modified because they are often placed into read only memory. "str" is a pointer being used to modify the constant.
In the second code, "string" is an array initializer, sort of short hand for
char str[7] = { 's', 't', 'r', 'i', 'n', 'g', '\0' };
"str" is an array allocated on the stack and can be modified freely.
Because the type of "whatever" in the context of the 1st example is const char * (even if you assign it to a non-const char*), which means you shouldn't try and write to it.
The compiler has enforced this by putting the string in a read-only part of memory, hence writing to it generates a segfault.
char *str = "string";
The above sets str to point to the literal value "string" which is hard-coded in the program's binary image, which is probably flagged as read-only in memory.
So str[0]= is attempting to write to the read-only code of the application. I would guess this is probably compiler dependent though.
To understand this error or problem you should first know difference b/w the pointer and array
so here firstly i have explain you differences b/w them
string array
char strarray[] = "hello";
In memory array is stored in continuous memory cells, stored as [h][e][l][l][o][\0] =>[] is 1 char byte size memory cell ,and this continuous memory cells can be access by name named strarray here.so here string array strarray itself containing all characters of string initialized to it.in this case here "hello"
so we can easily change its memory content by accessing each character by its index value
`strarray[0]='m'` it access character at index 0 which is 'h'in strarray
and its value changed to 'm' so strarray value changed to "mello";
one point to note here that we can change the content of string array by changing character by character but can not initialized other string directly to it like strarray="new string" is invalid
Pointer
As we all know pointer points to memory location in memory ,
uninitialized pointer points to random memory location so and after initialization points to particular memory location
char *ptr = "hello";
here pointer ptr is initialized to string "hello" which is constant string stored in read only memory (ROM) so "hello" can not be changed as it is stored in ROM
and ptr is stored in stack section and pointing to constant string "hello"
so ptr[0]='m' is invalid since you can not access read only memory
But ptr can be initialised to other string value directly since it is just pointer so it can be point to any memory address of variable of its data type
ptr="new string"; is valid
char *str = "string";
allocates a pointer to a string literal, which the compiler is putting in a non-modifiable part of your executable;
char str[] = "string";
allocates and initializes a local array which is modifiable
The C FAQ that #matli linked to mentions it, but no one else here has yet, so for clarification: if a string literal (double-quoted string in your source) is used anywhere other than to initialize a character array (ie: #Mark's second example, which works correctly), that string is stored by the compiler in a special static string table, which is akin to creating a global static variable (read-only, of course) that is essentially anonymous (has no variable "name"). The read-only part is the important part, and is why the #Mark's first code example segfaults.
The
char *str = "string";
line defines a pointer and points it to a literal string. The literal string is not writable so when you do:
str[0] = 'z';
you get a seg fault. On some platforms, the literal might be in writable memory so you won't see a segfault, but it's invalid code (resulting in undefined behavior) regardless.
The line:
char str[] = "string";
allocates an array of characters and copies the literal string into that array, which is fully writable, so the subsequent update is no problem.
String literals like "string" are probably allocated in your executable's address space as read-only data (give or take your compiler). When you go to touch it, it freaks out that you're in its bathing suit area and lets you know with a seg fault.
In your first example, you're getting a pointer to that const data. In your second example, you're initializing an array of 7 characters with a copy of the const data.
// create a string constant like this - will be read only
char *str_p;
str_p = "String constant";
// create an array of characters like this
char *arr_p;
char arr[] = "String in an array";
arr_p = &arr[0];
// now we try to change a character in the array first, this will work
*arr_p = 'E';
// lets try to change the first character of the string contant
*str_p = 'G'; // this will result in a segmentation fault. Comment it out to work.
/*-----------------------------------------------------------------------------
* String constants can't be modified. A segmentation fault is the result,
* because most operating systems will not allow a write
* operation on read only memory.
*-----------------------------------------------------------------------------*/
//print both strings to see if they have changed
printf("%s\n", str_p); //print the string without a variable
printf("%s\n", arr_p); //print the string, which is in an array.
In the first place, str is a pointer that points at "string". The compiler is allowed to put string literals in places in memory that you cannot write to, but can only read. (This really should have triggered a warning, since you're assigning a const char * to a char *. Did you have warnings disabled, or did you just ignore them?)
In the second place, you're creating an array, which is memory that you've got full access to, and initializing it with "string". You're creating a char[7] (six for the letters, one for the terminating '\0'), and you do whatever you like with it.
Assume the strings are,
char a[] = "string literal copied to stack";
char *p = "string literal referenced by p";
In the first case, the literal is to be copied when 'a' comes into scope. Here 'a' is an array defined on stack. It means the string will be created on the stack and its data is copied from code (text) memory, which is typically read-only (this is implementation specific, a compiler can place this read-only program data in read-writable memory also).
In the second case, p is a pointer defined on stack (local scope) and referring a string literal (program data or text) stored else where. Usually modifying such memory is not good practice nor encouraged.
Section 5.5 Character Pointers and Functions of K&R also discusses about this topic:
There is an important difference between these definitions:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.
Constant memory
Since string literals are read-only by design, they are stored in the Constant part of memory. Data stored there is immutable, i.e., cannot be changed. Thus, all string literals defined in C code get a read-only memory address here.
Stack memory
The Stack part of memory is where the addresses of local variables live, e.g., variables defined in functions.
As #matli's answer suggests, there are two ways of working with string these constant strings.
1. Pointer to string literal
When we define a pointer to a string literal, we are creating a pointer variable living in Stack memory. It points to the read-only address where the underlying string literal resides.
#include <stdio.h>
int main(void) {
char *s = "hello";
printf("%p\n", &s); // Prints a read-only address, e.g. 0x7ffc8e224620
return 0;
}
If we try to modify s by inserting
s[0] = 'H';
we get a Segmentation fault (core dumped). We are trying to access memory that we shouldn't access. We are attempting to modify the value of a read-only address, 0x7ffc8e224620.
2. Array of chars
For the sake of the example, suppose the string literal "Hello" stored in constant memory has a read-only memory address identical to the one above, 0x7ffc8e224620.
#include <stdio.h>
int main(void) {
// We create an array from a string literal with address 0x7ffc8e224620.
// C initializes an array variable in the stack, let's give it address
// 0x7ffc7a9a9db2.
// C then copies the read-only value from 0x7ffc8e224620 into
// 0x7ffc7a9a9db2 to give us a local copy we can mutate.
char a[] = "hello";
// We can now mutate the local copy
a[0] = 'H';
printf("%p\n", &a); // Prints the Stack address, e.g. 0x7ffc7a9a9db2
printf("%s\n", a); // Prints "Hello"
return 0;
}
Note: When using pointers to string literals as in 1., best practice is to use the const keyword, like const *s = "hello". This is more readable and the compiler will provide better help when it's violated. It will then throw an error like error: assignment of read-only location ‘*s’ instead of the seg fault. Linters in editors will also likely pick up the error before you manually compile the code.
First is one constant string which can't be modified. Second is an array with initialized value, so it can be modified.
Segmentation fault is caused when you try to access the memory which is inaccessible.
char *str is a pointer to a string that is nonmodifiable(the reason for getting segfault).
whereas char str[] is an array and can be modifiable..

Question about strings (as a variable from cs50) in C [duplicate]

The following code receives seg fault on line 2:
char *str = "string";
str[0] = 'z'; // could be also written as *str = 'z'
printf("%s\n", str);
While this works perfectly well:
char str[] = "string";
str[0] = 'z';
printf("%s\n", str);
Tested with MSVC and GCC.
See the C FAQ, Question 1.32
Q: What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
A: A string literal (the formal term
for a double-quoted string in C
source) can be used in two slightly
different ways:
As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values
of the characters in that array (and,
if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters,
and this unnamed array may be stored
in read-only memory, and which
therefore cannot necessarily be
modified. In an expression context,
the array is converted at once to a
pointer, as usual (see section 6), so
the second declaration initializes p
to point to the unnamed array's first
element.
Some compilers have a switch
controlling whether string literals
are writable or not (for compiling old
code), and some may have options to
cause string literals to be formally
treated as arrays of const char (for
better error catching).
Normally, string literals are stored in read-only memory when the program is run. This is to prevent you from accidentally changing a string constant. In your first example, "string" is stored in read-only memory and *str points to the first character. The segfault happens when you try to change the first character to 'z'.
In the second example, the string "string" is copied by the compiler from its read-only home to the str[] array. Then changing the first character is permitted. You can check this by printing the address of each:
printf("%p", str);
Also, printing the size of str in the second example will show you that the compiler has allocated 7 bytes for it:
printf("%d", sizeof(str));
Most of these answers are correct, but just to add a little more clarity...
The "read only memory" that people are referring to is the text segment in ASM terms. It's the same place in memory where the instructions are loaded. This is read-only for obvious reasons like security. When you create a char* initialized to a string, the string data is compiled into the text segment and the program initializes the pointer to point into the text segment. So if you try to change it, kaboom. Segfault.
When written as an array, the compiler places the initialized string data in the data segment instead, which is the same place that your global variables and such live. This memory is mutable, since there are no instructions in the data segment. This time when the compiler initializes the character array (which is still just a char*) it's pointing into the data segment rather than the text segment, which you can safely alter at run-time.
Why do I get a segmentation fault when writing to a string?
C99 N1256 draft
There are two different uses of character string literals:
Initialize char[]:
char c[] = "abc";
This is "more magic", and described at 6.7.8/14 "Initialization":
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
So this is just a shortcut for:
char c[] = {'a', 'b', 'c', '\0'};
Like any other regular array, c can be modified.
Everywhere else: it generates an:
unnamed
array of char What is the type of string literals in C and C++?
with static storage
that gives UB if modified
So when you write:
char *c = "abc";
This is similar to:
/* __unnamed is magic because modifying it gives UB. */
static char __unnamed[] = "abc";
char *c = __unnamed;
Note the implicit cast from char[] to char *, which is always legal.
Then if you modify c[0], you also modify __unnamed, which is UB.
This is documented at 6.4.5 "String literals":
5 In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals. The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. For character string literals, the array elements have
type char, and are initialized with the individual bytes of the multibyte character
sequence [...]
6 It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
6.7.8/32 "Initialization" gives a direct example:
EXAMPLE 8: The declaration
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
GCC 4.8 x86-64 ELF implementation
Program:
#include <stdio.h>
int main(void) {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compile and decompile:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output contains:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Conclusion: GCC stores char* it in .rodata section, not in .text.
If we do the same for char[]:
char s[] = "abc";
we obtain:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
so it gets stored in the stack (relative to %rbp).
Note however that the default linker script puts .rodata and .text in the same segment, which has execute but no write permission. This can be observed with:
readelf -l a.out
which contains:
Section to Segment mapping:
Segment Sections...
02 .text .rodata
In the first code, "string" is a string constant, and string constants should never be modified because they are often placed into read only memory. "str" is a pointer being used to modify the constant.
In the second code, "string" is an array initializer, sort of short hand for
char str[7] = { 's', 't', 'r', 'i', 'n', 'g', '\0' };
"str" is an array allocated on the stack and can be modified freely.
Because the type of "whatever" in the context of the 1st example is const char * (even if you assign it to a non-const char*), which means you shouldn't try and write to it.
The compiler has enforced this by putting the string in a read-only part of memory, hence writing to it generates a segfault.
char *str = "string";
The above sets str to point to the literal value "string" which is hard-coded in the program's binary image, which is probably flagged as read-only in memory.
So str[0]= is attempting to write to the read-only code of the application. I would guess this is probably compiler dependent though.
To understand this error or problem you should first know difference b/w the pointer and array
so here firstly i have explain you differences b/w them
string array
char strarray[] = "hello";
In memory array is stored in continuous memory cells, stored as [h][e][l][l][o][\0] =>[] is 1 char byte size memory cell ,and this continuous memory cells can be access by name named strarray here.so here string array strarray itself containing all characters of string initialized to it.in this case here "hello"
so we can easily change its memory content by accessing each character by its index value
`strarray[0]='m'` it access character at index 0 which is 'h'in strarray
and its value changed to 'm' so strarray value changed to "mello";
one point to note here that we can change the content of string array by changing character by character but can not initialized other string directly to it like strarray="new string" is invalid
Pointer
As we all know pointer points to memory location in memory ,
uninitialized pointer points to random memory location so and after initialization points to particular memory location
char *ptr = "hello";
here pointer ptr is initialized to string "hello" which is constant string stored in read only memory (ROM) so "hello" can not be changed as it is stored in ROM
and ptr is stored in stack section and pointing to constant string "hello"
so ptr[0]='m' is invalid since you can not access read only memory
But ptr can be initialised to other string value directly since it is just pointer so it can be point to any memory address of variable of its data type
ptr="new string"; is valid
char *str = "string";
allocates a pointer to a string literal, which the compiler is putting in a non-modifiable part of your executable;
char str[] = "string";
allocates and initializes a local array which is modifiable
The C FAQ that #matli linked to mentions it, but no one else here has yet, so for clarification: if a string literal (double-quoted string in your source) is used anywhere other than to initialize a character array (ie: #Mark's second example, which works correctly), that string is stored by the compiler in a special static string table, which is akin to creating a global static variable (read-only, of course) that is essentially anonymous (has no variable "name"). The read-only part is the important part, and is why the #Mark's first code example segfaults.
The
char *str = "string";
line defines a pointer and points it to a literal string. The literal string is not writable so when you do:
str[0] = 'z';
you get a seg fault. On some platforms, the literal might be in writable memory so you won't see a segfault, but it's invalid code (resulting in undefined behavior) regardless.
The line:
char str[] = "string";
allocates an array of characters and copies the literal string into that array, which is fully writable, so the subsequent update is no problem.
String literals like "string" are probably allocated in your executable's address space as read-only data (give or take your compiler). When you go to touch it, it freaks out that you're in its bathing suit area and lets you know with a seg fault.
In your first example, you're getting a pointer to that const data. In your second example, you're initializing an array of 7 characters with a copy of the const data.
// create a string constant like this - will be read only
char *str_p;
str_p = "String constant";
// create an array of characters like this
char *arr_p;
char arr[] = "String in an array";
arr_p = &arr[0];
// now we try to change a character in the array first, this will work
*arr_p = 'E';
// lets try to change the first character of the string contant
*str_p = 'G'; // this will result in a segmentation fault. Comment it out to work.
/*-----------------------------------------------------------------------------
* String constants can't be modified. A segmentation fault is the result,
* because most operating systems will not allow a write
* operation on read only memory.
*-----------------------------------------------------------------------------*/
//print both strings to see if they have changed
printf("%s\n", str_p); //print the string without a variable
printf("%s\n", arr_p); //print the string, which is in an array.
In the first place, str is a pointer that points at "string". The compiler is allowed to put string literals in places in memory that you cannot write to, but can only read. (This really should have triggered a warning, since you're assigning a const char * to a char *. Did you have warnings disabled, or did you just ignore them?)
In the second place, you're creating an array, which is memory that you've got full access to, and initializing it with "string". You're creating a char[7] (six for the letters, one for the terminating '\0'), and you do whatever you like with it.
Assume the strings are,
char a[] = "string literal copied to stack";
char *p = "string literal referenced by p";
In the first case, the literal is to be copied when 'a' comes into scope. Here 'a' is an array defined on stack. It means the string will be created on the stack and its data is copied from code (text) memory, which is typically read-only (this is implementation specific, a compiler can place this read-only program data in read-writable memory also).
In the second case, p is a pointer defined on stack (local scope) and referring a string literal (program data or text) stored else where. Usually modifying such memory is not good practice nor encouraged.
Section 5.5 Character Pointers and Functions of K&R also discusses about this topic:
There is an important difference between these definitions:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.
Constant memory
Since string literals are read-only by design, they are stored in the Constant part of memory. Data stored there is immutable, i.e., cannot be changed. Thus, all string literals defined in C code get a read-only memory address here.
Stack memory
The Stack part of memory is where the addresses of local variables live, e.g., variables defined in functions.
As #matli's answer suggests, there are two ways of working with string these constant strings.
1. Pointer to string literal
When we define a pointer to a string literal, we are creating a pointer variable living in Stack memory. It points to the read-only address where the underlying string literal resides.
#include <stdio.h>
int main(void) {
char *s = "hello";
printf("%p\n", &s); // Prints a read-only address, e.g. 0x7ffc8e224620
return 0;
}
If we try to modify s by inserting
s[0] = 'H';
we get a Segmentation fault (core dumped). We are trying to access memory that we shouldn't access. We are attempting to modify the value of a read-only address, 0x7ffc8e224620.
2. Array of chars
For the sake of the example, suppose the string literal "Hello" stored in constant memory has a read-only memory address identical to the one above, 0x7ffc8e224620.
#include <stdio.h>
int main(void) {
// We create an array from a string literal with address 0x7ffc8e224620.
// C initializes an array variable in the stack, let's give it address
// 0x7ffc7a9a9db2.
// C then copies the read-only value from 0x7ffc8e224620 into
// 0x7ffc7a9a9db2 to give us a local copy we can mutate.
char a[] = "hello";
// We can now mutate the local copy
a[0] = 'H';
printf("%p\n", &a); // Prints the Stack address, e.g. 0x7ffc7a9a9db2
printf("%s\n", a); // Prints "Hello"
return 0;
}
Note: When using pointers to string literals as in 1., best practice is to use the const keyword, like const *s = "hello". This is more readable and the compiler will provide better help when it's violated. It will then throw an error like error: assignment of read-only location ‘*s’ instead of the seg fault. Linters in editors will also likely pick up the error before you manually compile the code.
First is one constant string which can't be modified. Second is an array with initialized value, so it can be modified.
Segmentation fault is caused when you try to access the memory which is inaccessible.
char *str is a pointer to a string that is nonmodifiable(the reason for getting segfault).
whereas char str[] is an array and can be modifiable..

Why does strcpy specifically requires an array as first argument? (As opposed to a char* const ptr) [duplicate]

The following code receives seg fault on line 2:
char *str = "string";
str[0] = 'z'; // could be also written as *str = 'z'
printf("%s\n", str);
While this works perfectly well:
char str[] = "string";
str[0] = 'z';
printf("%s\n", str);
Tested with MSVC and GCC.
See the C FAQ, Question 1.32
Q: What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
A: A string literal (the formal term
for a double-quoted string in C
source) can be used in two slightly
different ways:
As the initializer for an array of char, as in the declaration of char a[] , it specifies the initial values
of the characters in that array (and,
if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters,
and this unnamed array may be stored
in read-only memory, and which
therefore cannot necessarily be
modified. In an expression context,
the array is converted at once to a
pointer, as usual (see section 6), so
the second declaration initializes p
to point to the unnamed array's first
element.
Some compilers have a switch
controlling whether string literals
are writable or not (for compiling old
code), and some may have options to
cause string literals to be formally
treated as arrays of const char (for
better error catching).
Normally, string literals are stored in read-only memory when the program is run. This is to prevent you from accidentally changing a string constant. In your first example, "string" is stored in read-only memory and *str points to the first character. The segfault happens when you try to change the first character to 'z'.
In the second example, the string "string" is copied by the compiler from its read-only home to the str[] array. Then changing the first character is permitted. You can check this by printing the address of each:
printf("%p", str);
Also, printing the size of str in the second example will show you that the compiler has allocated 7 bytes for it:
printf("%d", sizeof(str));
Most of these answers are correct, but just to add a little more clarity...
The "read only memory" that people are referring to is the text segment in ASM terms. It's the same place in memory where the instructions are loaded. This is read-only for obvious reasons like security. When you create a char* initialized to a string, the string data is compiled into the text segment and the program initializes the pointer to point into the text segment. So if you try to change it, kaboom. Segfault.
When written as an array, the compiler places the initialized string data in the data segment instead, which is the same place that your global variables and such live. This memory is mutable, since there are no instructions in the data segment. This time when the compiler initializes the character array (which is still just a char*) it's pointing into the data segment rather than the text segment, which you can safely alter at run-time.
Why do I get a segmentation fault when writing to a string?
C99 N1256 draft
There are two different uses of character string literals:
Initialize char[]:
char c[] = "abc";
This is "more magic", and described at 6.7.8/14 "Initialization":
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
So this is just a shortcut for:
char c[] = {'a', 'b', 'c', '\0'};
Like any other regular array, c can be modified.
Everywhere else: it generates an:
unnamed
array of char What is the type of string literals in C and C++?
with static storage
that gives UB if modified
So when you write:
char *c = "abc";
This is similar to:
/* __unnamed is magic because modifying it gives UB. */
static char __unnamed[] = "abc";
char *c = __unnamed;
Note the implicit cast from char[] to char *, which is always legal.
Then if you modify c[0], you also modify __unnamed, which is UB.
This is documented at 6.4.5 "String literals":
5 In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals. The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. For character string literals, the array elements have
type char, and are initialized with the individual bytes of the multibyte character
sequence [...]
6 It is unspecified whether these arrays are distinct provided their elements have the
appropriate values. If the program attempts to modify such an array, the behavior is
undefined.
6.7.8/32 "Initialization" gives a direct example:
EXAMPLE 8: The declaration
char s[] = "abc", t[3] = "abc";
defines "plain" char array objects s and t whose elements are initialized with character string literals.
This declaration is identical to
char s[] = { 'a', 'b', 'c', '\0' },
t[] = { 'a', 'b', 'c' };
The contents of the arrays are modifiable. On the other hand, the declaration
char *p = "abc";
defines p with type "pointer to char" and initializes it to point to an object with type "array of char" with length 4 whose elements are initialized with a character string literal. If an attempt is made to use p to modify the contents of the array, the behavior is undefined.
GCC 4.8 x86-64 ELF implementation
Program:
#include <stdio.h>
int main(void) {
char *s = "abc";
printf("%s\n", s);
return 0;
}
Compile and decompile:
gcc -ggdb -std=c99 -c main.c
objdump -Sr main.o
Output contains:
char *s = "abc";
8: 48 c7 45 f8 00 00 00 movq $0x0,-0x8(%rbp)
f: 00
c: R_X86_64_32S .rodata
Conclusion: GCC stores char* it in .rodata section, not in .text.
If we do the same for char[]:
char s[] = "abc";
we obtain:
17: c7 45 f0 61 62 63 00 movl $0x636261,-0x10(%rbp)
so it gets stored in the stack (relative to %rbp).
Note however that the default linker script puts .rodata and .text in the same segment, which has execute but no write permission. This can be observed with:
readelf -l a.out
which contains:
Section to Segment mapping:
Segment Sections...
02 .text .rodata
In the first code, "string" is a string constant, and string constants should never be modified because they are often placed into read only memory. "str" is a pointer being used to modify the constant.
In the second code, "string" is an array initializer, sort of short hand for
char str[7] = { 's', 't', 'r', 'i', 'n', 'g', '\0' };
"str" is an array allocated on the stack and can be modified freely.
Because the type of "whatever" in the context of the 1st example is const char * (even if you assign it to a non-const char*), which means you shouldn't try and write to it.
The compiler has enforced this by putting the string in a read-only part of memory, hence writing to it generates a segfault.
char *str = "string";
The above sets str to point to the literal value "string" which is hard-coded in the program's binary image, which is probably flagged as read-only in memory.
So str[0]= is attempting to write to the read-only code of the application. I would guess this is probably compiler dependent though.
To understand this error or problem you should first know difference b/w the pointer and array
so here firstly i have explain you differences b/w them
string array
char strarray[] = "hello";
In memory array is stored in continuous memory cells, stored as [h][e][l][l][o][\0] =>[] is 1 char byte size memory cell ,and this continuous memory cells can be access by name named strarray here.so here string array strarray itself containing all characters of string initialized to it.in this case here "hello"
so we can easily change its memory content by accessing each character by its index value
`strarray[0]='m'` it access character at index 0 which is 'h'in strarray
and its value changed to 'm' so strarray value changed to "mello";
one point to note here that we can change the content of string array by changing character by character but can not initialized other string directly to it like strarray="new string" is invalid
Pointer
As we all know pointer points to memory location in memory ,
uninitialized pointer points to random memory location so and after initialization points to particular memory location
char *ptr = "hello";
here pointer ptr is initialized to string "hello" which is constant string stored in read only memory (ROM) so "hello" can not be changed as it is stored in ROM
and ptr is stored in stack section and pointing to constant string "hello"
so ptr[0]='m' is invalid since you can not access read only memory
But ptr can be initialised to other string value directly since it is just pointer so it can be point to any memory address of variable of its data type
ptr="new string"; is valid
char *str = "string";
allocates a pointer to a string literal, which the compiler is putting in a non-modifiable part of your executable;
char str[] = "string";
allocates and initializes a local array which is modifiable
The C FAQ that #matli linked to mentions it, but no one else here has yet, so for clarification: if a string literal (double-quoted string in your source) is used anywhere other than to initialize a character array (ie: #Mark's second example, which works correctly), that string is stored by the compiler in a special static string table, which is akin to creating a global static variable (read-only, of course) that is essentially anonymous (has no variable "name"). The read-only part is the important part, and is why the #Mark's first code example segfaults.
The
char *str = "string";
line defines a pointer and points it to a literal string. The literal string is not writable so when you do:
str[0] = 'z';
you get a seg fault. On some platforms, the literal might be in writable memory so you won't see a segfault, but it's invalid code (resulting in undefined behavior) regardless.
The line:
char str[] = "string";
allocates an array of characters and copies the literal string into that array, which is fully writable, so the subsequent update is no problem.
String literals like "string" are probably allocated in your executable's address space as read-only data (give or take your compiler). When you go to touch it, it freaks out that you're in its bathing suit area and lets you know with a seg fault.
In your first example, you're getting a pointer to that const data. In your second example, you're initializing an array of 7 characters with a copy of the const data.
// create a string constant like this - will be read only
char *str_p;
str_p = "String constant";
// create an array of characters like this
char *arr_p;
char arr[] = "String in an array";
arr_p = &arr[0];
// now we try to change a character in the array first, this will work
*arr_p = 'E';
// lets try to change the first character of the string contant
*str_p = 'G'; // this will result in a segmentation fault. Comment it out to work.
/*-----------------------------------------------------------------------------
* String constants can't be modified. A segmentation fault is the result,
* because most operating systems will not allow a write
* operation on read only memory.
*-----------------------------------------------------------------------------*/
//print both strings to see if they have changed
printf("%s\n", str_p); //print the string without a variable
printf("%s\n", arr_p); //print the string, which is in an array.
In the first place, str is a pointer that points at "string". The compiler is allowed to put string literals in places in memory that you cannot write to, but can only read. (This really should have triggered a warning, since you're assigning a const char * to a char *. Did you have warnings disabled, or did you just ignore them?)
In the second place, you're creating an array, which is memory that you've got full access to, and initializing it with "string". You're creating a char[7] (six for the letters, one for the terminating '\0'), and you do whatever you like with it.
Assume the strings are,
char a[] = "string literal copied to stack";
char *p = "string literal referenced by p";
In the first case, the literal is to be copied when 'a' comes into scope. Here 'a' is an array defined on stack. It means the string will be created on the stack and its data is copied from code (text) memory, which is typically read-only (this is implementation specific, a compiler can place this read-only program data in read-writable memory also).
In the second case, p is a pointer defined on stack (local scope) and referring a string literal (program data or text) stored else where. Usually modifying such memory is not good practice nor encouraged.
Section 5.5 Character Pointers and Functions of K&R also discusses about this topic:
There is an important difference between these definitions:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.
Constant memory
Since string literals are read-only by design, they are stored in the Constant part of memory. Data stored there is immutable, i.e., cannot be changed. Thus, all string literals defined in C code get a read-only memory address here.
Stack memory
The Stack part of memory is where the addresses of local variables live, e.g., variables defined in functions.
As #matli's answer suggests, there are two ways of working with string these constant strings.
1. Pointer to string literal
When we define a pointer to a string literal, we are creating a pointer variable living in Stack memory. It points to the read-only address where the underlying string literal resides.
#include <stdio.h>
int main(void) {
char *s = "hello";
printf("%p\n", &s); // Prints a read-only address, e.g. 0x7ffc8e224620
return 0;
}
If we try to modify s by inserting
s[0] = 'H';
we get a Segmentation fault (core dumped). We are trying to access memory that we shouldn't access. We are attempting to modify the value of a read-only address, 0x7ffc8e224620.
2. Array of chars
For the sake of the example, suppose the string literal "Hello" stored in constant memory has a read-only memory address identical to the one above, 0x7ffc8e224620.
#include <stdio.h>
int main(void) {
// We create an array from a string literal with address 0x7ffc8e224620.
// C initializes an array variable in the stack, let's give it address
// 0x7ffc7a9a9db2.
// C then copies the read-only value from 0x7ffc8e224620 into
// 0x7ffc7a9a9db2 to give us a local copy we can mutate.
char a[] = "hello";
// We can now mutate the local copy
a[0] = 'H';
printf("%p\n", &a); // Prints the Stack address, e.g. 0x7ffc7a9a9db2
printf("%s\n", a); // Prints "Hello"
return 0;
}
Note: When using pointers to string literals as in 1., best practice is to use the const keyword, like const *s = "hello". This is more readable and the compiler will provide better help when it's violated. It will then throw an error like error: assignment of read-only location ‘*s’ instead of the seg fault. Linters in editors will also likely pick up the error before you manually compile the code.
First is one constant string which can't be modified. Second is an array with initialized value, so it can be modified.
Segmentation fault is caused when you try to access the memory which is inaccessible.
char *str is a pointer to a string that is nonmodifiable(the reason for getting segfault).
whereas char str[] is an array and can be modifiable..

Why can't I change char array later?

char myArray[6]="Hello"; //declaring and initializing char array
printf("\n%s", myArray); //prints Hello
myArray="World"; //Compiler says"Error expression must a modifiable lvalue
Why can't I change myArray later? I did not declare it as const modifier.
When you write char myArray[6]="Hello"; you are allocating 6 chars on the stack (including a null-terminator).
Yes you can change individual elements; e.g. myArray[4] = '\0' will transform your string to "Hell" (as far as the C library string functions are concerned), but you can't redefine the array itself as that would ruin the stack.
Note that [const] char* myArray = "Hello"; is an entirely different beast: that is read-only memory and any changes to that string is undefined behaviour.
Array is a non modifiable lvalue. So you cannot modify it.
If you wish to modify the contents of the array, use strcpy.
Because the name of an array cannot be modified, just use strcpy:
strcpy(myArray, "World");
You can't assign to an array (except when initializing it in its declaration. Instead you have to copy to it. This you do using strcpy.
But be careful so you don't copy more than five characters to the array, as that's the longest string it can contain. And using strncpy in this case may be dangerous, as it may not add the terminating '\0' character if the source string is to long.
You can't assign strings to variables in C except in initializations. Use the strcpy() function to change values of string variables in C.
Well myArray is the name of the array which you cannot modify. It is illegal to assign a value to it.
Arrays in C are non-modifiable lvalues. There are no operations in C that can modify the array itself (only individual elements can be modifiable).
Well myArray is of size 6 and hence care must be taken during strcpy.
strcpy(myArray,"World") as it would result in overflow if the source's string length is more than the destination's (6 in this case).
A arrays in C are non-modifiable lvalues. There are no operations in C that can modify the array itself (only individual elements can be modifiable).
A possible and safe method would be
char *ptr = "Hello";
If you want to change
ptr = strdup("World");
NOTE:
Make sure that you free(ptr) at the end otherwise it would result in memory leak.
You cannot assign naked arrays in C. However you can assign pointers:
char const *myPtr = "Hello";
myPtr = "World";
Or you can assign to the elements of an array:
char myArray[6] = "Hello";
myArray[0] = 'W';
strcpy(myArray, "World");

How do strings and char arrays work in C?

No guides I've seen seem to explain this very well.
I mean, you can allocate memory for a char*, or write char[25] instead? What's the difference? And then there are literals, which can't be manipulated? What if you want to assign a fixed string to a variable? Like, stringVariable = "thisIsALiteral", then how do you manipulate it afterwards?
Can someone set the record straight here? And in the last case, with the literal, how do you take care of null-termination? I find this very confusing.
EDIT: The real problem seems to be that as I understand it, you have to juggle these different constructs in order to accomplish even simple things. For instance, only char * can be passed as an argument or return value, but only char[] can be assigned a literal and modified. I feel like it's obvious that we frequently/always needs to be able to do both, and that's where my pitfall is.
What is the difference between an allocated char* and char[25]?
The lifetime of a malloc-ed string is not limited by the scope of its declaration. In plain language, you can return malloc-ed string from a function; you cannot do the same with char[25] allocated in the automatic storage, because its memory will be reclaimed upon return from the function.
Can literals be manipulated?
String literals cannot be manipulated in place, because they are allocated in read-only storage. You need to copy them into a modifiable space, such as static, automatic, or dynamic one, in order to manipulate them. This cannot be done:
char *str = "hello";
str[0] = 'H'; // <<== WRONG! This is undefined behavior.
This will work:
char str[] = "hello";
str[0] = 'H'; // <<=== This is OK
This works too:
char *str = malloc(6);
strcpy(str, "hello");
str[0] = 'H'; // <<=== This is OK too
How do you take care of null termination of string literals?
C compiler takes care of null termination for you: all string literals have an extra character at the end, filled with \0.
Your question refers to three different constructs in C: char arrays, char pointers allocated on the heap, and string literals. These are all different is subtle ways.
Char arrays, which you get by declaring char foo[25] inside a function, that memory is allocated on the stack, it exists only within the scope you declared it, but exactly 25 bytes have been allocated for you. You may store whatever you want in those bytes, but if you want a string, don't forget to use the last byte to null-terminate it.
Character pointers defined with char *bar only hold a pointer to some unallocated memory. To make use of them you need to point them to something, either an array as before (bar = foo) or allocate space bar = malloc(sizeof(char) * 25);. If you do the latter, you should eventually free the space.
String literals behave differently depending on how you use them. If you use them to initialize a char array char s[] = "String"; then you're simply declaring an array large enough to exactly hold that string (and the null terminator) and putting that string there. It's the same as declaring a char array and then filling it up.
On the other hand, if you assign a string literal to a char * then the pointer is pointing to memory you are not supposed to modify. Attempting to modify it may or may not crash, and leads to undefined behavior, which means you shouldn't do it.
Since other aspects are answered already, i would only add to the question "what if you want the flexibility of function passing using char * but modifiability of char []"
You can allocate an array and pass the same array to a function as char *. This is called pass by reference and internally only passes the address of actual array (precisely address of first element) instead of copying the whole. The other effect is that any change made inside the function modifies the original array.
void fun(char *a) {
a[0] = 'y'; // changes hello to yello
}
main() {
char arr[6] = "hello"; // Note that its not char * arr
fun(arr); // arr now contains yello
}
The same could have been done for an array allocated with malloc
char * arr = malloc(6);
strcpy(arr, "hello");
fun(arr); // note that fun remains same.
Latter you can free the malloc memory
free(arr);
char * a, is just a pointer that can store address, which might be of a single variable or might be the first element of an array. Be ware, we have to assign to this pointer before actually using it.
Contrary to that char arr[SIZE] creates an array on the stack i.e. it also allocates SIZE bytes. So you can directly access arr[3] (assuming 3 is less than SIZE) without any issues.
Now it makes sense to allow assigning any address to a, but not allowing this for arr, since there is no other way except using arr to access its memory.

Resources