I was looking at some obfuscated c code and I saw that someone used this :
while(putchar(*foo++))
Lets just say foo is a char* for now.
How does this work?
With while(putchar(*foo++)) the body of the while loop is executed until the controlling expression is false. The controlling expression is putchar(*foo++). The controlling expression is evaluated before the loop body is executed for each iteration.
putchar outputs a character to stdout, but also returns the value of the written character. If the written character is \0, i.e., the null terminator of a string, then putchar returns \0 (the null character which has all bits set to zero). Zero is a false value in the controlling expression, so the loop ends.
*foo++ increments the pointer foo by one (one byte if foo is a pointer to char) after dereferencing it. The expression *foo++ is equivalent to *(foo++) since the ++ post-increment operator has higher precedence than * dereference operator, i.e., the post-increment is associated with the pointer, not the dereferenced value. The value of the pointer foo is read (the address stored in foo). This value is post-incremented, i.e., the value of the full expression putchar(*foo) is computed for use in the while loop, then the value of foo is incremented and updated (the address stored in foo is incremented).
Putting all of this together, while(putchar(*foo++)) prints each character of the string pointed to by foo to stdout in order (including the terminating null byte). If the body of the while loop is not empty, other actions may occur after each character is printed.
Note that, e.g., while (*foo++) is a common idiom in C for iterating over the characters of a string. But while (putchar(*foo++)) is not a common idiom, and not good code.
Other than being somewhat obfuscated, this putchar construction behaves differently than Standard Library functions which write strings to output; the Standard Library functions never write the final null byte of a string to output.
This unexpected behavior could cause problems if, e.g., code attempts to use the final position of the pointer foo to determine the length of the string without some care.
This construct is also not safe. putchar can return EOF in the event of a write error; since the loop does not check for this condition, a write error would likely lead to an infinite loop and potential undefined behavior. Such a condition could occur in the event of a hardware failure, or (more likely) if stdout has been redirected to a file.
It's equivalent to this:
int ret;
do {
ret = putchar(*foo);
foo++;
} while( ret != 0 );
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