Hacker News new | ask | show | jobs
by sltkr 1910 days ago
The value introduced by C++ was type safety. In C, it's way too easy for the format string to get out of sync with the type of the arguments, e.g.:

    printf("%d", my_long_var);
Might seem correct and work correctly on one platform, but fail on another. scanf() is arguably even worse since it can cause memory corruption.

These days compilers have diagnostics to catch those errors, but if you rely on those you can't use dynamic format strings, which means you're effectively using a subset of C with a stronger type checker than C. That's a pretty good state but it's definitely not "old style printf()"; old style printf() was insecure.

And don't get me started on the convoluted macro invocations necessary to correctly convert int32_t, int64_t, size_t and ptrdiff_t. And that's with the newest standard: IIRC there was no standard way to print long long in C, at the time when C++ already supported it.

1 comments

Maybe C++ fixed type safety, but it introduced lot of complexity and bugs for no actual added value. For instance, because of stateful ios objects, it's close to impossible to write correct code outputing hex on first attempt. I'm sure that lot of C++ code outputing hex is just plain wrong.

Given that C++ keeps getting more and more complex features, it is just amazing that C++ I/O is still so inconvenient, opaque and ultra-verbose.

I mean it's not particularly pretty but what's so bad about this?

    std::cout << std::hex << my_int << std::dec << std::endl;
That construction is ok. But usually you want formatted output, let's say align to byte, and pad with zeroes. I've seen oftentimes (and did myself):

    std::cout << std::setfill('0') << std::setw(2) << std::hex << my_int << std::dec << std::endl;
This appears to work until someone change the alignment to left somewhere in the code. Hence the correct code is:

    // C++ type-safe equiv to printf("%-02x",my_int) - it's called progress
    std::cout << std::right << std::setfill('0') << std::setw(2) << std::hex << my_int << std::dec << std::endl;
Also, is it relevant to keep the final 'dec' when we assume we can't assert the ios left/right state, so why could we assert the hex/dec state? Or maybe was it a bug to change alignment to left, and not restore it to right afterwards? Or maybe should you restore ios state in some centrol place, and never pass your iostream to some external libs? Discussions and wars ahead. Note that the bug above is very nasty because it will change say "02" into "20", which looks perfectly valid.

Note: I just noticed that in C++20, there is new formatted string proposal. You can't stop progress, but neither can you speed it up it seems.

Note2: the 'std::' spam is yet another indication that C++ is lacking common sense and utterly broken.