1

How would I get my replace_char function to work properly?

The way that I am trying it in the function below returns segmentation faults using gcc in Ubuntu.

I have tried other ways, but each time I try to change the value, I get a fault.

int main (void)
{  
  char* string = "Hello World!";

  printf ("%s\n", string);
  replace_char(string, 10, 'a');
  printf ("%s\n", string);
}

void replace_char(char str[], int n, char c)
{
  str[n] = c;
}
K-ballo
  • 80,396
  • 20
  • 159
  • 169
Kyle Uithoven
  • 2,414
  • 5
  • 30
  • 43

2 Answers2

6

There is nothing wrong with your replace_char function. The problem is that you are trying to modify a string literal ("Hello World!") and that's undefined behavior. Try making a copy of the string instead, like this:

char string[] = "Hello World!";
K-ballo
  • 80,396
  • 20
  • 159
  • 169
  • 1
    *""Hello World!" is actually a `char const*` but its allowed to convert to `char*` to support legacy code."* - actually, this is true for C++ (actually, it's a `const` `char` array), but in C literals are defined as non-`const` `char[]` that result in UB on modification. – Matteo Italia Sep 28 '11 at 22:03
  • 2
    First, a string literal is an array, not a pointer. It's implicitly converted to a pointer in most contexts, but `sizeof "Hello World!"`, for example, yields the size of the array (12), not the size of a pointer. Second, string literals are `const` in C++, but not in C. In C, string literals are still non-const (to avoid breaking legacy code), but attempting to modify one is undefined behavior. – Keith Thompson Sep 28 '11 at 22:05
  • @KeithThompson: high five! :) – Matteo Italia Sep 28 '11 at 22:08
  • 1
    @MatteoItalia ... and so do ours. 8-)} – Keith Thompson Sep 28 '11 at 22:15
  • 1
    @Matteo Italia, Keith Thompson: Thanks, I edited my answer. I'm C++ biased :P – K-ballo Sep 28 '11 at 22:19
  • I suppose the question above was unclear. I am trying to make my replace_char function functional (no pun intended) with the main code provided. I now know why I cannot change the value since it is 'literal'. Is there a way to copy the value from the literal to char string[] and change the value and put it back into str? – Kyle Uithoven Sep 28 '11 at 22:58
5

Edit

To get the 'suggestion' of editing string in place, you can edit the pointer inplace:

void replace_char(char*& str, int n, char c)
{
  str = strdup(str);
  str[n] = c;
}

int main()
{
    char* string = "Hello World!";
    string = replace_char(string, 10, 'a');

    // ...
    free(string);
}

Note you now have to remember to call free on the string after calling this. I suggest, instead, that you do what I suggested before: wrap the literal in strdup if required. That way you don 't incur the cost of allocating a copy all the time (just when necessary).


The problem is that "Hello World' is a const literal char array.

const char* conststr = "Hello World!";
char * string = strdup(conststr);

i assume the problem will be gone

Explanation: Compilers can allocate string literals in (readonly) data segment. The conversion to a char* (as opposed to const char*) is actually not valid. If you use use e.g.

gcc -Wall test.c

you'd get a warning.

Fun experiment:

Observe here that (because it is Undefined Behaviour) compilers can do funny stuff in such cases:

http://ideone.com/C39R6 shows that the program wouldn't 'crash' but silently fail to modify the string literal unless the string was copied.

YMMV. Use -Wall, use some kind of lint if you can, and do unit testing :){

sehe
  • 374,641
  • 47
  • 450
  • 633
  • added a fun experiment that highlights the **Undefined** in Undefined Behaviour – sehe Sep 28 '11 at 22:07
  • **PS**: did you note the [_other_ instance of Undefined Behaviour that I fixed](http://stackoverflow.com/questions/2270899/c89-vs-c99-gcc-compiler) in the sample here http://ideone.com/C39R6 ? (hint: assuming C89) – sehe Sep 28 '11 at 22:10
  • I understand that it is a literal char array, but I would like to edit it and replace it in that function. – Kyle Uithoven Sep 29 '11 at 17:18
  • @KyleUithoven: good luck. I suggest you send a letter to you compiler vendor, or better yet to the standards committee... – sehe Sep 29 '11 at 17:23
  • @KyleUithoven: re `Is there a way to copy the value from the literal to char string[] and change the value and put it back into str?`: yes it is, the code shows how to. Note that the `string` value itself is **not** a constant, just the data pointed to initially. So you can update `string` to point to the modified data (elsewhere). For the record, I have updated the answer with a demonstration of how you _could_ do this. – sehe Sep 29 '11 at 17:25
  • In the above answer, you note to remember to call free on the string. Is that just free(str)? str.free? If not, what would be the proper syntax for that. – Kyle Uithoven Sep 29 '11 at 18:16
  • @KyleUithoven: edited. I think it would be a good idea to just read a few [man-page](http://linux.die.net/man/3/strdup) (and [this](http://linux.die.net/man/3/free)) or a [good book](http://stackoverflow.com/questions/803522/after-kr-what-book-to-use-to-learn-programming-in-plain-c) – sehe Sep 29 '11 at 21:00