1

I have written the following replace function which replaces substring inside a big string as follows:

void replace(char *str1, char *str2, int start, int end)
{
    int i,j=0;
    for(i=start; i<end; i++, j++)
        *(str1+i)=*(str2+j);
}

It works fine when I put a string as replace("Move a mountain", "card", 0,4), but when I declare a string using pointer array like char *list[1]={"Move a mountain"} and pass it to the function as replace(list[0], "card",0,4), it gives me a segmentation fault.

Not able to figure it out. Can anybody please explain this to me?

user2719152
  • 939
  • 3
  • 11
  • 20
  • 3
    Literal strings in C are really *read-only* arrays of characters. Attempting to modify the contents of such an array leads to [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior). That's why all pointers to literal strings should really be `const char *`. – Some programmer dude Feb 11 '19 at 08:12
  • 6
    On an unrelated note, the expression `*(str1+i)` is *exactly* equal to `str1[i]`. The latter is usually easier to read and understand, as well as little shorter to write. This equivalence is true for all arrays and pointers. – Some programmer dude Feb 11 '19 at 08:14
  • I just wonder why the C++ compiler warns about assigning string literals to `char*` but the C compiler does not. The OP's problem would not have come up had the C compiler also warned about it. – Duck Dodgers Feb 11 '19 at 08:31
  • 2
    @JoeyMallone In C a literal string is an array of `char`. In C++ a literal string is an array of `const char`. The array in C can't be modified though so it effectively is read-only, but it's still not an array of constant characters. This is just *one* of the way C and C++ differs, and why many here don't like the term "C/C++" or using both C and C++ tags for questions. – Some programmer dude Feb 11 '19 at 08:33
  • Related to https://stackoverflow.com/q/164194/694576. – alk Feb 11 '19 at 08:44
  • @SanderDeDycker Yeah...I meant list[0]. I would update the question. – user2719152 Feb 11 '19 at 09:25

1 Answers1

7

The code of function replace looks fine, yet all the ways you call it introduce undefined behaviour:

First, with replace("Move a mountain", "card", 0,4), you are passing a string literal as argument for str1, which is modified in replace then. Modifying a string literal is undefined behaviour, and if it "works", it is just luck (more bad luck than good luck, actually).

Second char *list[1]={"Move a mountain"} is similar but introduces another issue: char*list is an array of pointers, and you initialize list[0] to point to string literal ""Move a mountain". So passing list[0] would again lead to UB due to modifying a string literal. But then you pass list[1], which is out of bounds and therefore introduces undefined behaviour. Again, everything can happen, segfaulting being just one such possibility.

Write

char list[] = "Move a mountain"; // copies string literal into a new and modifiable array 
replace(list, "card",0,4)

and it should work better.

alk
  • 69,737
  • 10
  • 105
  • 255
Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58