Usually when someone says they want to convert from decimal to BCD, they're talking about more than one decimal digit.
BCD is often packed into two decimal digits per byte (because 0..9 fit in 4 bits, as you've shown), but I think it's more natural to use an array of bytes, one per decimal digit.
An n-bit unsigned binary number will fit into ceil(n*log_2(10)) = ceil(n/log10(2)) decimal digits. It will also fit in ceil(n/3) = floor((n+2)/3)) decimal digits, since 2^3=8 is less than 10.
With that in mind, here's how I'd get the decimal digits of an unsigned int:
#include <algorithm>
#include <vector>
template <class Uint>
std::vector<unsigned char> bcd(Uint x) {
std::vector<unsigned char> ret;
if (x==0) ret.push_back(0);
// skip the above line if you don't mind an empty vector for "0"
while(x>0) {
Uint d=x/10;
ret.push_back(x-(d*10)); // may be faster than x%10
x=d;
}
std::reverse(ret.begin(),ret.end());
// skip the above line if you don't mind that ret[0] is the least significant digit
return ret;
}
Of course, if you know the width of your int type, you may prefer fixed length arrays. There's also no reason to reverse at all if you can remember the fact that the 0th digit is the least significant and reverse only on input/output. Keeping the least significant digit as the first simplifies digit-wise arithmetic ops in the case that you don't use a fixed number of digits.
If you want to represent "0" as the single "0" decimal digit rather than the empty digit-string (either is valid), then you'd check specifically for x==0.