0

I understand that following code returns segmentation fault because it tries to write to the part of memory where q points to (some random address) and this part of memory is not allowed to write by given process:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
  char* p = "Hello";
  char* q;

  strcpy(q, p);
  printf("%s\n", q);
}

I also understand that it can be easily fixed by dynamically allocating appropriate amount of memory and pointing q to this memory, so p content can be safely copied to q:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
  char* p = "Hello";
  char* q = (char*)malloc(6*sizeof(char));

  strcpy(q, p);
  printf("%s\n", q);
}

But why following example is working?

#include <stdio.h>

int main(){
  char* p = "Hello";
  printf("%s\n", p);
}

Isn't char* p = "Hello"; also pointing to some unknown memory which is not allowed to write by given process?

Flimzy
  • 60,850
  • 13
  • 104
  • 147
Wakan Tanka
  • 5,906
  • 11
  • 47
  • 96

3 Answers3

2

The code

char* p = "Hello";

creates an array of six chars and sets them to "Hello" (the sixth char is the null-char). Then, it writes the memory address of this array to p. So p points to an initialized memory segment.

Concerning your second example: p contains the memory address of the char array "Hello". If you want q to contain the same memory address, you have to use the command

q = p;

In the code

q = &p;

the types are incompatible, because q has type char*, whereas &p has type char**.

Xaver
  • 844
  • 7
  • 15
1

When you write char* p = "Hello";, the compiler will create a char array in a part of memory that is read-only at runtime, filled as {'H', 'e', 'l', 'l', 'o', '\0'}. The pointer p is filled with the address of this array. So the address is valid, it can be read from safely but not written to, it can be passed as a readable string to C's string functions, and you never need to worry about mallocing and freeing string literals because they represent static arrays.

alter igel
  • 5,696
  • 3
  • 16
  • 38
1

When you write char *p = "Hello";, the compiler internally creates a const char[6] to hold the string litteral, and then copy its address to p. Unfortunately, the type of a string litteral is not const, so you do not get any warning telling you that you are dropping a const attribute, but the string litteral shall not be modified.

So p point to a well defined memory zone and you can safely read from it for example with printf("%s\n", p);

The problem is that the string litteral shall not be modified, and trying to use the pointer for writing like in p[1] = 'a'; invokes undefined behaviour. In common implementations, the compiler actually uses a read-only segment to store string litterals and you get a memory violation or segment violation error if you try to overwrite it.

But it is not unknown memory simply read-only one.

Serge Ballesta
  • 121,548
  • 10
  • 94
  • 199