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 */
}
}
}
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.