-2

I would like to understand the difference between the format of having a pointer to an array of characters declared and initialised to an array of choice example char *s = "Hello"; and having it done the more common way of declaring an array char s[] = "Hello";

I recreated memset and tried using it on the first declaration example which resulted in a bus error. I don't understand why because from what I gather is that in C, the first method of declaring and initialising an array should be the same as the second one in terms of how they are both stored on the stack memory and a pointer being able to interact with the arrays address when the array is passed by reference to my function.

The problem is that I can not alter the first version of the array but I can print it using printf which suggests that altering it should therefore be possible because it IS there somewhere in memory and I have access to its address.

I would just like to have a clear explanation as to what is going on under the hood for both formats. What makes the one achieve the objective yet the other doesn't.

My aim is to just understand as much as I can about C, your help will be appreciated in getting me to soon appreciate the beauty of the language and having a clear picture of how all of its components work together to efficiently solve a problem.

Attached below is my code:

Format that works with my ft_memset.c funct
format that works with my ft_memset.c funct

Format that doesn't work, yet able to print the array
format that doesn't work, yet able to print the array - why??

Cristik
  • 30,989
  • 25
  • 91
  • 127
  • Please ignore that the printf statements have been commented out in the non-working format attachment, it was already tested and resulted in a bus error. I just want a clear picture of C's memory and it seems like I still don't see it too well from this exercise. – This is Glory Mar 04 '18 at 04:15
  • 1
    https://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s – J.Doe Mar 04 '18 at 04:38

2 Answers2

2

In char *s = “Hello", ”Hello" is a string literal that causes an array of char to be created and set to contain “Hello” and a terminating null character. Because it is a string literal, the rules of C say you should not try to write to it.

The statement also defines s to be a pointer to char and initializes s to point to the first character.

The statement char s[] = “Hello” defines s to be an array of char and initializes it to contain “Hello” and a terminating null character. Because this is an ordinary array, not a string literal, you are allowed to write to it. (In this statement, ”Hello” is technically a string literal, but it is used only to initialize the array s, as if by copying its contents into s. s is not the string literal and does not point to the string literal; it is a separate array.)

The compiler is allowed to put the string literal anywhere it likes. It does not have to be on the stack. Because you are getting an error when you try to write to it, it seems the compiler is putting it in the read-only constants section of the program.

When you declare s to be an array, compilers will typically put the array on the stack if s has automatic storage duration (is declared inside a function without static, extern, or a thread-storage qualifier). (Using the stack is not a requirement of C. Some compilers may put the array elsewhere, but this generally happens only in special circumstances, such as when compiling for a very limited environment.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

Trying to modify string literals are undefined behavior. §6.4.5¶7(which is what you did in first case).

There lies a question whether some implementation would allow you to make changes to it or not. standard don't impose anything on that line. It just says that modifying a string literal is undefined behavior.

Going from what I said, in most implementations string literals are put in read only section making them non-modifiable. On your case you saw the problem - because you were trying to modify it and that resulted in BUS error. (In your case you saw this).

First one is just a pointer pointing to the string literal - so everything said holds for it.

Second one is creating an array and initializing it with the content of the string literal and this is modifiable. You are safe to do whatever you want with this. §6.7.9¶14 Based on where you put it may have static storage duration or automatic storage duration. (static storage duration - when placed in file scope, automatic when placed in block scope).

From the very standard quoted earlier - it says from §6.4.5¶6 (Regarding the storage of string literals)

The multibyte character sequence is then used to initialize an array of static storage duration and length just sufficient to contain the sequence.

The links are from C11 standard N1570

user2736738
  • 30,591
  • 5
  • 42
  • 56