Don't have much to add, but +1 to using the implicit modularity of fixed-size (and known size; use inttypes!) unsigneds.

Put another way, it's fixed point 0.16 (or whatever), fractional cycles.

Most anything you would do with degrees, can be done in any other unit. sin/cos implementations can be adjusted, it's just a matter of changing coefficients and bit shifts, etc.

There's also a... maybe more esoteric route? Which, I've thought about here and there, but which probably isn't worthwhile for most applications. In any case, consider the argument of a complex number, which we store as a tuple z = [a, b], which might be char, int, whatever. If |z| is normalized, we can simply multiply it by any other (complex) number to change the angle -- the basis of the CORDIC algorithm for example. We trivially extend it into a direction vector, if we're doing something spacial or geometrical -- this can be useful in video games, and I used such a scheme for a raycaster (WOLF3D style) engine way back when* -- but the fact that you're handling ~double the information, that normalization is awkward, etc., means it probably isn't going to be your first pick when you just need an angle.

*The maybe most interesting part here is, the screen vector is automatically scaled for perspective correction -- that is, the vectors cast from camera origin to view plane (well, line), automatically scale the rays cast to walls, giving perspective-correct lengths returned from the "cast" function. I've seen tons of trig corrections (both preparing the vectors, and correcting the ray lengths), and hackery around singularities (axis aligned vectors), in others' implementations of raycasters, so I felt pretty proud of the general, direction-invariant solution I came up with.

Tim