skip to Main Content

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.

  1. How are you supposed to use these functions given the discrepancy in types and their native sizes?

  2. 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


  1. How are you supposed to use these functions given the discrepancy in types and their native sizes?

    By using the appropriate format.

    Type Format Notes
    long signed int "%ld"
    long long signed int "%lld"
    int32_t "%" PRId32 #include <inttypes.h>
    int64_t "%" PRId64 #include <inttypes.h>

    How are you supposed to deal with the reality that you may change your type somewhere?

    You could use the same approach as for int32_t: a typedef, plus a macro for the format.

    Login or Signup to reply.
  2. 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

    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 a size_t when "%zu" should be used. size_t and unsigned 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search