0
votes

I do

char ch = 'c';

and then

char *char_ptr = &ch;
*(char_ptr+1) = 'h';
*(char_ptr+2) = '\0';

This works correctly when I print it using

printf("char_ptr as string = %s\n", char_ptr);

But when I do

char *char_ptr = 'c';
*(char_ptr+1) = 'h';
*(char_ptr+2) = '\0';

Then it causes segmentation fault. What is the reasoning behind this?

4
Please note that it didn't work in either case. Both are undefined behaviour, for different reasons.paddy
Agreed, it needs modifications in first case as well.user883499
@paddy: The second is formally non-compilable. char *char_ptr = 'c'; is a constraint violation. It is illegal to use non-zero integer constant to initialize a pointer.AnT

4 Answers

4
votes

'c' is an integral constant which, under ASCII systems, evaluates to 0x63.

That, and the addresses immediately after it, are almost certainly go to be invalid addresses to start poking information into.

In fact, even the first one is undefined behaviour since ch only has a single character allocated and you're trying to change information beyond that. It may work depending on how your compiler lays out memory and stack frames but it's still a very bad idea.

A more correct way of doing this would be:

char char_ptr[3] = "c";    // Allocate three bytes to ensure room.
*(char_ptr+1) = 'h';       // or char_ptr[1] = 'h';
*(char_ptr+2) = '\0';      // or char_ptr[2] = '\0';
0
votes
char *char_ptr = 'c'; 

That is a pointer and it needs to point to an address which is what &ch is.

0
votes

The assignment char *char_ptr = addr will point the pointer char_ptr to the memory address addr. In your examples, &ch is the address of ch, while 'c' is just a char value thus not a valid memory address.

0
votes
char ch = 'c';

this is a C command, that (internally) reserves 1 Byte to store/hold the character "c" in it, on an (for the user) unknown memory position (if the application is running, then on a place into the memory, that the application reserves before it is execute).

char *char_ptr = &ch;

This is a command, that:

  1. declare a "array" of characters (char's), indicate as pointer with the asterisk, 1a. the size of this "pointer" variable has the size of the users CPU bandwide (a user under 32-Bit OS, has 4 Bytes in length, a user under a 64-Bit OS has 8 Bytes in size. This is the default size.

  2. with the ampsign &, you reference to a memory position - it will point to "ch", the command, you have given by char ch = 'c'; note: this is a reference, no pointer ! As such, the memory value "c" will not change. As such, you can get undefined breakable/behavoiur, because you "reserved" with ch only one Byte, and the application is willing to remember this on a good OS, the application crash. This has the background, that you reference "to the memory" position, and this part of memory will be protected by the application OS. If you have luck, the size of _ptr is the same as your computer cpu arch. If you have luck, the operation system will copy the one byte of ch to the position to the address of _ptr.

    *(char_ptr+1) = 'h';

with this command, you "get" the address of _ptr, and right 1 byte left (counting from 0), and assign the character 'h' to this position, and override the content of the 4 Byte sized _ptr (32-Bit cpu). This make the result "cxxx" to "chxx" - xxx stands for random bytes.

*(char_ptr+2) = '\0';

the same here: you "get" the address of _ptr, and jump 2 byte to right (counting from 0), and assign the character 'h', to this position, and override the content of the 4 Byte sized _ptr (32-bit cpu). This make the result "chxx" to "ch\0x". This means, you formed a literal/string, that is indicate with a null terminated character, that is used to mark the string as to be ended there on this position.

printf("char_ptr as string = %s\n", char_ptr);

this print the _ptr (string) value from the char_ptr at its memory address on screen. Because you have the literal "ch\0x"; You will get see the string "ch" the command sequence \n is provided, and has a "newline" starting as result.