Search code examples
cc99stdint

How to use abs and div with fixed-size integers


In C99 we have fixed-size integer types, defined in stdint.h. In stdlib.h we have the abs and div functions which operate on ints, as well as their long int/long long int counterparts labs, llabs, ldiv, lldiv.

Since the size of int/long/long long varies based on platform and used compiler I wonder how to chose the right variant of abs/div when using fixed-size integers like int16_t, int32_t or int64_t?


Solution

  • Assuming, that you are able to use a C11 compiler, you could use Generic macros feature and define wrapper, that covers fixed-size integers. An example might look like:

    #include <math.h>
    #include <inttypes.h>
    #include <stdio.h>
    
    #define safe_abs(n) _Generic((n), \
        signed char: abs(n), short: abs(n), int: abs(n), long: labs(n), long long: llabs(n))
    
    int main(void)
    {
        int8_t n1 = -123;
        printf("n1 = %" PRId8 "\n", safe_abs(n1));
    
        int16_t n2 = -1234;
        printf("n2 = %" PRId16 "\n", safe_abs(n2));
    
        int32_t n3 = -123456;
        printf("n3 = %" PRId32 "\n", safe_abs(n3));
    
        int64_t n4 = -12345678910;
        printf("n4 = %" PRId64 "\n", safe_abs(n4));
    
        return 0;
    }
    

    The trick is that these fixed-size integers are just type definitions for standard integer types.