Reversing a '\0' terminated C string in place?

c, dereference, pointers, reverse

Solution

Lots of questions... trying to capture answers to each:

/* does *str = opal or does *str = o since the pointer str is type char? */

`*str` is `'o'` since it points at the first character

/* what is the difference between char* end and char *end? and is *end pointing to opal now? */

There is no difference between `char *end` and `char* end`. It gets trickier when you write

char* a, b;

since this is equivalent to

char *a, b;

and not, as you might think

char *a, *b;

This is why it's cleaner to write `char *end;`.

And `end` is pointing to `opal` now - `*end` is `'o'`.

if (str) { /* if str isn't null? */

Yes - testing that you did not get passed a NULL pointer

To test that you did not get passed a string of length 0, you would have to test `*str` (after testing that `str` is not NULL, otherwise you get a segmentation error for "daring to look at *NULL")

while (str < end) { /* why not *str < *end? is this asking while o < l? */

Testing the pointers - one is moving towards the end, the other is moving back. When you meet in the middle you stop; otherwise you do the swap twice, and there will be no net effect...

 *str++ = *end; /* what is the difference between *str++ and ++str? does *str++ = l? */

You first copy the value of `*end` to `*str`, then you increment the `str` pointer. If you put `++str`, you increment first, then use it. And that would mean that you put the `l` in place of the `p` instead of in place of the `o`.

edit one critique on your code (going beyond the questions you asked, and responding to a comment from @chux): when you test for `if(str){}` you really need an `else return;` statement, since you actually do `end--;` and then use `*end`. Pretty sure that `0xFFFFFFFFFFFFFFFF` is almost always an invalid address...

If you in fact were testing for `if(*str!='\0')` then you should still just return (an empty string is "irreversible" - or rather, it doesn't need anything to be considered reversed).

By the way, I much prefer making the condition explicit (like I did just then); not only does it show your intention more clearly, but the compiler might actually complain if you did `if(str!='\0')` or `if(*str != NULL)` since the types you are comparing are incompatible. This means you will have code that is more robust, more readable, and more likely to do what you intended.

Problem

I have some conceptual questions about reversing a null terminated C string, and clarification questions about the nature of pointers. The input might be ``` char arr[] = "opal"; ``` and the code: ``` void reverse(char *str) { /* does *str = opal or does *str = o since the pointer str is type char? */ char* end = str; /* what is the difference between char* end and char *end? and is *end pointing to opal now? */ char tmp; if (str) { /* if str isn't null? */ while (*end) ++end; } --end; /* end pointer points to l now */ while (str < end) { /* why not *str < *end? is this asking while o < l? */ tmp = *str; /* tmp = o */ *str++ = *end; /* what is the difference between *str++ and ++str? does *str++ = l? */ *end-- = tmp; /* *end points to o */ } } } ```

Original source