Handling numbers too big for base data types

Question from Skip#4185

How do you handle numbers that are too big to fit into the largest available data types?

Would you define a struct containing multiple large data types and somehow split up the number?

I'm not trying to do something like that, but i'm just curious if anyone knows what the right course of action would be in such a case

End of day you should use a bigint library, but you can also "build" it yourself if you are so inclined

#include <stdio.h>
#include <stdlib.h>

enum bigint_kind {
    _64_BIT,
    _MORE_THAN_64_BIT
};

union bigint_value {
    long u64;
    struct {
        long* blocks_of_64_bit;
        size_t length;
    } bigger_than_u64;
};

struct bigint {
    enum bigint_kind _kind;
    union bigint_value _value;
};

struct bigint* bigint_from_long(long value) {
    struct bigint* i = calloc(0, sizeof(struct bigint));
    i->_kind = _64_BIT;
    union bigint_value value_;
    value_.u64 = value;
    i->_value = value_;
    return i;
}

void bigint_free(struct bigint* i) {
    if (i->_kind == _MORE_THAN_64_BIT) {
        free(i->_value.bigger_than_u64.blocks_of_64_bit);
    }
    free(i)
}

If you are using rote C it can be a bit of a nightmare to track memory now for darn numbers since any of them can now contain a heap allocated array and in C you don't have "move semantics" like c++ so you end up doing unneeded heap allocations to track stuff and also there is some pointer indirection here which is annoying.

TL;DR; use a library for it

python, java, etc it should "just work". python's numerics auto promote and java has BigInteger. But the only languages on your profile are C and python. so if you are asking the question...

Exercise for the reader

struct bigint* bigint_add(struct bigint* a, struct bigint* b) {
    if (a->_kind == _64_BIT) {
        if (b->_kind == _64_BIT) {
            
        }
        else {
            
        }
    }
    else {
        
    }
}

<- Index