#include <stdio.h>
// Represents 1 zettabyte (ZiB = 2⁷⁰ bytes) using a 128‑bit struct
// Because a zettabyte does not fit in 64‑bit integers,
// the only portable way in C is to represent it using a 128‑bit emulation struct
typedef struct {
unsigned long long hi; // high 64 bits
unsigned long long lo; // low 64 bits
} u128;
// Construct a u128 from high + low 64-bit parts
u128 make_u128(unsigned long long hi, unsigned long long lo) {
u128 x;
x.hi = hi;
x.lo = lo;
return x;
}
// Print u128 as decimal (simple, slow but correct)
void print_u128(u128 x) {
// Convert to decimal by repeated division by 10
char buf[64] = {0};
int pos = 63;
unsigned long long hi = x.hi;
unsigned long long lo = x.lo;
while (hi != 0 || lo != 0) {
unsigned long long rem = 0;
// Manual 128-bit divide-by-10
unsigned long long new_hi = hi / 10;
unsigned long long hi_rem = hi % 10;
unsigned __int128 wide = ((unsigned __int128)hi_rem << 64) | lo;
unsigned long long new_lo = (unsigned long long)(wide / 10);
rem = (unsigned long long)(wide % 10);
hi = new_hi;
lo = new_lo;
buf[--pos] = '0' + rem;
}
if (pos == 63) {
buf[--pos] = '0';
}
printf("%s", &buf[pos]);
}
int main(void) {
/*
1 ZiB = 2^70 bytes
2^70 = 1,180,591,620,717,411,303,424
In 128-bit form:
hi = 2^(70-64) = 2^6 = 64
lo = 0
*/
u128 ZETTABYTE = make_u128(64ULL, 0ULL);
printf("1 ZiB in u128 = ");
print_u128(ZETTABYTE);
printf(" bytes\n");
return 0;
}
/*
run:
1 ZiB in u128 = 1180591620717411303424 bytes
*/