On Linux 64 bit and Windows MinGW a long is most likely 64-bit wide. On Visual Studio 64-bit a long is 32-bit wide. Suppose I have a fixed integer type of 32-bit or 64-bit, when I call something like printf() I have to specify what type is being read. If I get it wrong it’s UB. So my either 32 or 64-bit type isn’t specifically an int, or a long, or a long long, but typedeffed to God only knows what.
int32_t my_number;
fprintf("%l", my_number); // LONG IS STIPULATED TO BE "AT LEAST" 32-BITS BUT NOT GUARANTEED
int64_t my_number;
fprintf("%ll", my_number); // LONG LONG IS STIPULATED TO BE "AT LEAST" 64-BITS BUT NOT GUARANTEED
The same thing applies to other functions like ltoa(). I guess the problem lies in the fact that from the function’s point of view it only knows a ‘pointer’, and just runs full steam ahead based on which function the programmer called, this seems really crazy error-prone and dangerous, not to mention anything of the fact that if you change one of your types anywhere in your code everywhere that calls these functions makes you computer go boom.
-
How are you supposed to use these functions given the discrepancy in types and their native sizes?
-
How are you supposed to deal with the reality that you may change your type somewhere?
Should I even use these functions? Rust people go on about how unsafe C++ is but in comparison to this it’s a bubble-wrapped utopian paradise. I usually program C++, would be it better to go through all the types and template the hell out of everything so that each type calls the write function? Would this entail checking something like:
Like this:
template <typename T>
void value_to_ascii(const char* buffer, int max_size, const T& val)
{
if constexpr(std::is_same_v<T, long>)
ltoa();
else if constexpr(std::is_same_v<T, int>)
itoa();
}
2
Answers
By using the appropriate format.
long signed int
"%ld"
long long signed int
"%lld"
int32_t
"%" PRId32
#include <inttypes.h>
int64_t
"%" PRId64
#include <inttypes.h>
You could use the same approach as for
int32_t
: a typedef, plus a macro for the format.As a first step:
Enable your good compiler’s options to look for specifier/type mismatches.
This will catch many easy-to-find errors.
It may miss things like
"%lu"
matched to asize_t
when"%zu"
should be used.size_t
andunsigned long
may be the same type on your system, but not others.For something different in C, you can review Formatted print without the need to specify type matching specifiers using _Generic for another approach.