While I was putting together a to-uppercase function in C++ I noticed that I did not receive the expected output in C.
C++ function
#include <iostream>
#include <cctype>
#include <cstdio>
void strupp(char* beg)
{
while (*beg++ = std::toupper(*beg));
}
int main(int charc, char* argv[])
{
char a[] = "foobar";
strupp(a);
printf("%s\n", a);
return 0;
}
Output as expected:
FOOBAR
C function
#include <ctype.h>
#include <stdio.h>
#include <string.h>
void strupp(char* beg)
{
while (*beg++ = toupper(*beg));
}
int main(int charc, char* argv[])
{
char a[] = "foobar";
strupp(a);
printf("%s\n", a);
return 0;
}
The output is the expected result with the first character missing
OOBAR
Does anyone know why the result gets truncated while compiling in C?
The problem is that there is no sequence point in
while (*beg++ = toupper(*beg));
So we have undefined behavior. What the compiler is doing in this case is evaluating beg++
before toupper(*beg)
In C where in C++ it is doing it the other way.
while (*beg++ = std::toupper(*beg));
leads to undefined behavior.
Whether *beg++
is sequenced before or after std::toupper(*beg)
is unspecified.
The simple fix is to use:
while (*beg = std::toupper(*beg))
++beg;
The line
while (*beg++ = toupper(*beg));
contains a side effect on an entity that's being used twice. You can not know, whether or not beg++ is executed before or after the *beg (inside the toupper). You're just lucky that both implementations show both behaviors, as I'm pretty sure it's the same for C++. (However, there were some rule changes for c++11, which I'm not certain of - still, it's bad style.)
Just move the beg++ out of the condition:
while (*beg = toupper(*beg)) beg++;
with respect to above answer, the 'f' is never passed inside function, you should try using this:
while ((*beg = (char) toupper(*beg))) beg++;