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.
does *str = opal or does *str = o since the pointer str is type char?
*str
dereferences the pointer, which is of type char*
, so the type you get is char
. That char
will be the value pointed to by str
, which will be 'o'
.
what is the difference between char* end and char *end?
Nothing.
and is *end pointing to opal now?
Yes, well, close. end
is pointing to exactly the same adddress as str
, which is the start of your string of characters. *end
is a character type, not a pointer. Its value will be 'o'
.
if str isn't null?
Correct, doing a boolean test on a pointer is a standard test. It evaluates to a 'true' value if the pointer is not null and 'false' otherwise. Note that this is not the same as a zero value. The C standard allows any value to represent a null address.
why not *str < *end? is this asking while o < l?
No, it is comparing the actual memory address. It says to loop while str
points to an earlier part of the string than end
. You'll notice that during the loop, str
increases, and end
decreases. So eventually they will pass eachother or meet at the same character (ie the middle of the string).
what is the difference between *str++ and ++str? does *str++ = l?
str++
is applied first, which increments str
and returns its previous value, then the *
unary operator derferences to give the character at that old position. Yes, the first time around, the 'l'
from end
will be assigned to the beginning of the string (where str
used to point before it was incremented). The tmp
is used to carry the old character and assign it to end
. This is a standard 'swap' operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With