0

hello to all programmers, I can't understand something

  1. char a[]="hello"

  2. char* b="salam"

the first question is why can't we modify 2,for example b[0]='m', I know that 2 gets stored as compile time constant BUT I can't understand what does it mean and what is the quiddity of 2 ?

and second question:

3.

char a[]="hello";

char* c=a;

c[0]='r';

Now we can modify and then print c, but we couldn't modify 2 ! why?

I can't understand the concept of those pointers please explain it to me

anastaciu
  • 23,467
  • 7
  • 28
  • 53
S MEHDI M
  • 37
  • 1
  • 5

3 Answers3

5

char a[] = "hello;" is a null terminated array of characters, the array will be initialized with the charaters you specify and the size of it will be deduced by the compiler, in this case it will have space for 6 characters, these are mutable, the charaters are copied to the array, you can change them at will. e.g. a[0] = 'x' will change hello to xello.

char* c = a; just makes the pointer c point to a, the same operations can be performed in c as you are really operating in a.

char* b = "salam" is a different animal, b is a pointer to a string literal, these are not meant to be modified, they don't get stored in an array like a, they are read only and are usually stored in some read only section of memory, either way the behavior of editing b is undefined, i.e. b[0] = 'x' is illegal as per the language rules.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
3

char a[]="hello";

This creates an array like this:

   +---+---+---+---+---+----+
a: | h | e | l | l | o | \0 |
   +---+---+---+---+---+----+

The array is modifiable and you can write other characters to it later if you like (although you cannot write more than 5 or 6 of them).

char* b="salam";

This uses a string literal to create a constant string somewhere, that variable b is then a pointer to. I like to draw it like this:

   +-------+
b: |   *   |
   +---|---+
       |
       V
     +---+---+---+---+---+----+
     | s | a | l | a | m | \0 |
     +---+---+---+---+---+----+

There are two differences here: (1) b is a pointer, not an array as a was. (2) the string here (that b points to) is probably in nonwritable memory. But a was definitely in writable memory.

char* c=a;

Now c is a pointer, pointing at the earlier-declared array a. The picture looks like this:

   +---+---+---+---+---+----+
a: | h | e | l | l | o | \0 |
   +---+---+---+---+---+----+
     ^
     |
      \
       |
   +---|---+
c: |   *   |
   +-------+

And the array a was modifiable, so there's no problem doing c[0] = 'r', and we end up sounding like Scooby-Doo and saying:

   +---+---+---+---+---+----+
a: | r | e | l | l | o | \0 |
   +---+---+---+---+---+----+
     ^
     |
      \
       |
   +---|---+
c: |   *   |
   +-------+

The key difference (which can be quite subtle) is that a string literal in source code like "hello" can be used in two very different ways. When you say

char a[] = "hello";

the string literal is used as the initial value of the array a. But the array a is an ordinary, modifiable array, and there's no problem writing to it later.

Most other uses of string literals, however, work differently. When you say

char *b = "salam";

or

printf("goodbye\n");

those string literals are used to create and initialize "anonymous" string arrays somewhere, which are referred to thereafter via pointers. The arrays are "anonymous" in that they don't have names (identifiers) to refer to them, and they're also usually placed in read-only memory, so you're not supposed to try to write to them.

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
0

Let's start of with your first question:
We have 2 strings, a and b

char a[] = "hello";
char *b = "salam";

The first string can be modified, this is because it uses a different memory segment than the second string. It is stored in the data segment of the program, and we have write access to the data segment so we can modify it.

The second string is a pointer to a string, we cannot modify string literals (pointers to strings) since c specifies that this is undefined behavior.

The address of b will just point to somewhere in the program where that string is stored. This string should preferably be declared const since it can't be modified anyways.

const char *b = "salam";

Now let's look at the second question: The code you provided for the second question is perfectly valid,

char a[] = "hello";
char *c = a;,
c[0] = 'r';

We have a, which stores the actual string and if using ASCII it consists of 6 bytes 'h', 'e', 'l', 'l', 'o', '\0' c points to a we can verify this with this code

#include <stdio.h>

int main(void) {
    char a[] = "hello";
    char *c = a;
    c[0] = 'r';
    printf("a: %p\nc: %p\n", &a, &*c);
}

And we'll get output as such

a: 0x7ffe3c94ecf2
c: 0x7ffe3c94ecf2

They both point to the same address, the start of the array when we do

c[0] // It essentially means *(c + 0) = in other words the address which c points to + 0 and then we subscript this is how subscripting works a[1] = *(a + 1), etc...

So pretty much c in this case points to

0x7ffe3c94ecf2

c + 0 =

0x7ffe3c94ecf2

Access that address and modify the character.

  • `The second string is a pointer to a string, that string is stored in rodata / text segment, which is a read only segment, we cannot write to that memory, we do not have the privileges to do that.` Generally C does not know anything about the segments. It is about the implementation. Modifications of **string literals** is UB and shall not be performed. – 0___________ Aug 27 '21 at 19:35
  • Yes you're correct we're not certain about which segment it is stored in but this is most likely the case at least on windows / unix – love4shells___ Aug 27 '21 at 19:37
  • maybe arduino? Atmega ? AVR8 bit where string literals are in RAM? How can you know – 0___________ Aug 27 '21 at 19:41
  • Like i said, yes you're correct we're not certain about which segment it is stored in. But i think it's safe to say most people write in a Unix / Windows environment. Sorry i assumed he isn't using DOS or Arduino lol – love4shells___ Aug 27 '21 at 19:47
  • You assumption is wrong. I do programming in C as my daytime job for 30y. And I almost never program unix or windows systems. Simply remove that segment part from your answer. Attempt to modify the string literal is UB. C standard says that. – 0___________ Aug 27 '21 at 19:51
  • Yes sorry i forgot to do that and i will do it now. I didn't think that far as I'm used to programming in a Windows / Unix environment myself. It's my mistake – love4shells___ Aug 27 '21 at 19:52