Discussion: Weakly Typed, Strongly Puzzling

Execute the code to understand the output and gain insights into implicit type conversions and their effects.

Run the code

Now, it’s time to execute the code and observe the output.

Press + to interact
#include <iostream>
int main()
{
std::cout << +!!"";
}

Understanding the output

Wait, what? Is this legal C++? What does it even mean, and why does it print 1?

While C++ is a statically typed language, it’s not particularly strongly typed. As we’ve seen throughout the course, C++ is, in fact, very eager to implicitly convert between types without explicitly telling it to. For instance, in the Aristotle’s Sum of Parts puzzle, we saw how the sum of two char types is not a char; in the A Strong Point puzzle, we saw how we should declare our constructors explicit to avoid them taking part in implicit conversions; and in the A Little Sum Thing puzzle, we saw how implicit conversions between arithmetic types can lead to unexpected results.

This eagerness is something we inherited back in the day when C++ was designed as an extension of C. If we did it over today, this abundance of implicit conversions would be high on the list of things we’d want to change.

So, which implicit conversions are in play here, what is the final type of this expression, and why is the result 1?

Breaking down the expression

Let’s discuss the expression in detail below:

  • Let’s start from the right, with the "" expression. This is a string literal, and as we discussed in the String Theory puzzle, the type of a string literal is “array of n const char,” with n being 1 in this case (for the implicit \0 terminator).

  • Next is the ! operator, which negates its operand. But how do we negate an array of characters? That doesn’t make sense, does it? Indeed, it doesn’t, but the operand to the ! operator is contextually converted to bool before being negated. Converting an array to bool doesn’t make sense either, but as we saw in the “String Theory” puzzle, arrays can be implicitly converted to pointers, and pointers can again be converted to bool. When a pointer is converted to bool, it converts to false if it’s a null-pointer and to true otherwise. Since the pointer in this case is non-null (it points to our string literal), it converts to true. Finally, the ! operator negates this, so we arrive at false. You could argue that this entire conversion sequence doesn’t really make sense either, and we’d agree, but at least we can understand how each step works and how they combine to arrive at this result.

  • Next up is another !, which, this time, simply negates our boolean value false, giving us true.

  • Finally, there’s the unary +. The operand to unary + goes through integral promotions, which, for bool, means converting false to 0 and true to 1. The operator itself doesn’t do anything; its result is the same as its operand (after promotion). So our boolean value true finally turns into the integer value 1, which gets printed.

Whether or not the compiler should warn about any of this is another discussion, but none of the major ones do, even with -Wall or -Wextra for GCC and Clang, and /Wall for MSVC. The compiler might be able to provide some warnings, though, if we turn those warnings on explicitly. For instance, Clang will warn about the string-to-bool conversion if given the -Wstring-conversion option (which is not included in -Wall or -Wextra). Check the compiler’s documentation for the list of warnings it supports.

Recommendations

Here are some recommendations to ensure better code practices and avoid confusion.

  • Turn on as many warnings as you can: Enable as many compiler warnings as possible to catch potential issues early.

  • Be aware that not all warnings are included in the maximum warning levels for each compiler: Check your compiler’s documentation to ensure that you are aware of all available warnings.

  • Don’t write code like this in real life: Avoid writing code that relies on complex or non-intuitive implicit conversions. It’s better to write clear and understandable code.

Level up your interview prep. Join Educative to access 70+ hands-on prep courses.