How to define a zettabyte constant in C

2 Answers

0 votes
// A zettabyte (binary) is:
              
// 1 ZiB = 2 ^ 70 bytes = 1,180,591,620,717,411,303,424 bytes

// a 64‑bit system cannot represent a zettabyte (2⁷⁰ bytes) in a 64‑bit intege
                          
#include <stdio.h>
#include <locale.h>

// 64‑bit integer cannot shift left by 70 bit
// #define ZETTABYTE     (1ULL << 70)                 // 1 ZiB (binary) // Error 
// #define ZETTABYTE_DEC 1000000000000000000000ULL    // 1 ZB  (decimal)

#define ZETTABYTE     1180591620717411303424ULL      // 1 ZiB (binary)
#define ZETTABYTE_DEC 1000000000000000000000ULL      // 1 ZB  (decimal)

int main(void) {
    unsigned long long size = ZETTABYTE; // Error: integer constant is too large for its type

    printf("1 ZiB = %llu bytes\n", size);
    
    // Enable locale so %'llu prints commas (glibc only)
    setlocale(LC_NUMERIC, "");

    printf("1 ZiB = %'llu bytes\n", size);

    return 0;
}



/*
run:

1 ZiB = 0 bytes
1 ZiB = 0 bytes

*/


 



answered May 2 by avibootz
0 votes
#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

*/

 



answered May 2 by avibootz

Related questions

...