Typedef
I like to avoid typedefs without semantic meaning. In other words, ull
is just a shortcut for unsigned long long
, not a meaningful type.
I'm assuming you care you about the maximum value more than you care that the type is specifically an unsigned long long
, so I would use uint64_t
from stdint.h
instead of your typedef.
If you are going to use a typedef, try to give it a more meaningful name (which is pretty difficult in this situation without resorting to a pretty vague name like number
or something).
while
vs for
This is more of a personal style thing, but I tend to use for
loops over while
loops whenever reasonable:
for (; num > 0; num = (num - 1) / base) {
*(word++) = alpha[(num - 1) % base];
}
Depending on how much you want to cram into the for
loop (it can definitely go too far), you could even take it a step farther so that the for
handles all of the iteration type stuff:
for (; num > 0; num = (num - 1) / base, ++word) {
*word = alpha[(num - 1) % base];
}
Variable declaration
It looks like you're using C99 or newer, so nu
doesn't need to be declared at the top of main
. Instead, declare it in the tightest scope at the closest place to initial usage possible. In other words, nu
should be declared in the for loop in which its used (for (ull nu = 0; ...; ...)
).
Comments
These are both super minor:
/* "OSR43" was added to show that the letters of alpha
are NOT in alphabetical order */
alpha
has OSR34
in it not OSR43
.
// word always contains null-terminator
I would put this inside of the loop instead of under calloc
since I'm assuming the meaning is something like "Since word
never decreases in length, it's always null terminated." Seeing it under calloc
made my first thought "well of course a calloc
allocated string is null terminated!" before realizing what you really meant.
sizeof
It's kind of iffy in situations this simple, but I like to use sizeof
on the thing it's involved with instead of a type. In other words, I would have done char *word = calloc(30, sizeof(*word));
. It looks a bit stupid in the simple case, but in complex code, it can be quite nice since it's impossible to change the type of the variable and forget to change the sizeof
. It's kind of a DRY manifestation of sorts.
Performance
This code's working fine but I need to speed it up as much as possible. How do I do it?
I'm not much an optimization expert, so perhaps someone will come along with some magic, but as far as I can tell, conv
isn't going to get meaningfully faster than it already is.
There is, fortunately a trivial 'optimization' is available with the output. In particular, puts
, though simpler (puts(s)
is equivalent to printf("%s\n", s)
), is much faster than printf
. Changing from printf
to puts
cuts the time the program takes to run on my computer from 8 seconds to 2.75 seconds.