Here's a method that should work. Note that it destructively modifies the bigint that you pass to it, so if you care about the value there, copy it to a temporary scratch buffer before calling the method.
Also, this isn't the most optimized version you could write, but if you're asking how to do it on here you probably aren't concerned yet about micro-optimization with this.
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
bool is_zero(uint8_t *bigi_data, int bigi_size) {
int i = 0;
while((i < bigi_size) && (bigi_data[i] == 0)) {
i++;
}
return (i >= bigi_size);
}
uint8_t bigdivmod(uint8_t *bigi_data, int bigi_size, uint8_t divisor) {
int i = 0;
uint16_t ans = 0;
while((i < bigi_size) && (bigi_data[i] == 0)) {
i++;
}
for (; i < bigi_size; i++) {
ans = ans*256 + bigi_data[i];
bigi_data[i] = ans / divisor;
ans = ans % divisor;
}
return (uint8_t)ans;
}
static const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
char *bigitoa(uint8_t *bigi_data, int bigi_size, char *out, int base) {
/* Assumes that "out" has enough room. DESTRUCTIVE TO BIGI, so copy */
/* if you care about the value */
/* Only really works for non-negative values */
int i = 0;
uint8_t swp;
int j;
if ((base < 2) || (base > 36)) {
return NULL;
}
if (is_zero(bigi_data, bigi_size)) {
out[0] = '0';
out[1] = '\0';
return out;
}
while (!is_zero(bigi_data, bigi_size)) {
out[i++] = digits[bigdivmod(bigi_data, bigi_size, base)];
}
out[i] = 0;
for (j = 0; j < i/2; j++) {
swp = out[i - 1 - j];
out[i - 1 - j] = out[j];
out[j] = swp;
}
return out;
}
int main(int argc, char *argv[]) {
uint8_t test_data[] = { 0xd5, 0x3c, 0xeb, 0x9d, 0x32, 0xc6, 0xca, 0x06 };
int test_data_len = sizeof(test_data);
char *p;
/* Times 3 because we can use three digits to represent 256. If changing */
/* the base below from "10", change this factor. */
p = malloc(3*test_data_len + 1);
printf("Test data works out to %s\n",
bigitoa(test_data, test_data_len, p, 10));
return 0;
}