2

Program 1:

 void function(char arr[])
 {
   arr[0] = 'X';
   printf("%s",arr);
 }       

 int main()
 {
   function("MyString");  
 }

Output: Segmentation fault

Program 2:

   int main()
   {
    char arr[] = "MyString";
    arr[0] = 'X';
    printf("%s",arr);
   }

Output: XyString

What is the difference between program 1 and program 2? In prog1 also string value (not by reference) is passed to array so it should copy to array and allow to modify it? But it is throwing segmentation fault. In prog2 successfully allowing to change the arr[]. Why in prog1 it is not working?

nobody
  • 19,814
  • 17
  • 56
  • 77
bhr
  • 131
  • 1
  • 10
  • I think you are (rightly) confused by the similarity of the parameter declaration in `void function(char arr[])` and the variable declaration `char arr[] = "MyString";`. The function declaration could have equivalently been written as `void function(char *arr)` which is probably more common. The character array you pass in the call "decays", as one says, to a pointer to its first element. Arrays do that in most contexts. The literal is part of your executable and as such often not writable. Although visually very similar, the contents of the string literal is _copied_ to `arr` in program 2. – Peter - Reinstate Monica May 23 '14 at 06:43
  • I was running out of space... The difference is that `arr` in program 2 is a true array which is created "on the stack" like any other local variable. The contents of "MyString" is copied into it. Like with any other local variable it's perfectly safe to write to it. – Peter - Reinstate Monica May 23 '14 at 06:46

1 Answers1

2
  1. Prog 1: You are passing a string literal, which is sent to the function as const char*. You can not change a const object.
  2. Prog 2:You are using a non-const character array, which can be modified.

From your comment:

In prog1 also string value (not by reference) is passed to array so it should copy to array and allow to modify it?

Wrong. In program 1, the string literal is placed somewhere in memory (possibly in read only memory since it is constant), and then a const char* which points to that memory location is sent. The character array is not sent as parameter, only the address of first character.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Rakib
  • 7,435
  • 7
  • 29
  • 45
  • When a parameter is passed by value to function, then its value needs to be copied and should be allowed. but why it is not happening in this case? – bhr May 22 '14 at 15:47
  • The parameter is the pointer to the characters, not the characters. –  May 22 '14 at 15:48
  • @user3665615 Arrays are always passed by a pointer to their first element. `char * a` and `char a[]` is the same when we talk about parameters. – glglgl May 22 '14 at 15:48
  • @PeterSchneider, clearly the OP cannot with his compiler, and this is the correct behavior, it does not matter if compilers conforming previous standards allow it. Compilers who allow this also allows to write unsafe code like this. – Rakib May 22 '14 at 16:24
  • What I want to say is that before C++11 it was legally possible to initialize a char pointer with a string literal, for compatibility reasons. The language and the compilers allowed it. What happened when you wrote to it was undefined though. C++11 finally forbids it, but the OP's compiler clearly allows the assignment. So the string literal decays to a _char *_, or the OP could not pass it to the function! Cf. http://stackoverflow.com/questions/2245664/string-literals-in-c. – Peter - Reinstate Monica May 22 '14 at 16:37
  • @PeterSchneider, may be I am missing something, care to explain what you meant by "But you often can!" in first comment? what can be done often? passing string literal or changing content of a `const char*`? – Rakib May 22 '14 at 16:47
  • @user3665615, A function parameter never has array type. The compiler silently changes it to a pointer type. So you actually have `void function(char*);`, which is why this is not "pass by value". – aschepler May 22 '14 at 17:15
  • I meant both. As I said in my clarifying post: Legally you could (up to C++11) initialize a char* with a string literal. Apart from that you can cast away const and write to memory pointed to by a const char * on many systems, depending on what the pointer actually points to. – Peter - Reinstate Monica May 22 '14 at 20:50
  • @PeterSchneider, the question is not about whether string literal can be sent for char array/pointer, so my reply did not answer it. The point is segmentation fault occurred as a result of trying to change content of a `const char*`, and it **can not be done legally**. may be in some compiler it does not cause any problem, but const casting a `const` object is **UB**. So your "But you often can" can be taken as just a hint that some compiler does not fully conform to standard. – Rakib May 23 '14 at 02:55
  • Half correct. Casting away const is certainly never UB. Reading from an object after casting away const is perfectly fine. _Modifying_ an object after casting away const _may or may not_ be UB, depending on the object. To sum up: The const-qualification of a pointer has no inherent coupling with the constness of the object it points to -- one can always (regardless of pointer qualification) safely write to non-const objects; and one invokes, as we have just seen in the pre-C++11 example, UB by writing to a const object (equally regardless of the pointer qualification). – Peter - Reinstate Monica May 23 '14 at 06:36