C++ manual padding for alignment

Started by
1 comment, last by Zahlman 17 years, 6 months ago
Hi, I have a general c++ question... I'm looking for how to do manual padding. I've searched on google and couldn't find anything so I figured someone here might know. I've seen padding to 4 bytes done like this: totalSize = (totalSize + 0x3) & ~0x3; But I'd like to know if that can be generalized? If I want to pad to the next 16 bytes boundary, how can I do it? totalSize = (totalSize + 0x7) & ~0x7; ? totalSize = (totalSize + 0x15) & ~0x15; ? Or the algorithm can't be generalized? Thank you!
Advertisement
It can. However, you should use either 15 or 0xF. 0x15 is incorrect.
This really isn't a C++ question; it's an arithmetic question. To "pad" to a multiple of N bytes, you need to find the smallest value X which is (a) divisible by N, and (b) at least as large as your starting value.

We can do this by adding (N-1), dividing by N (discarding the remainder) and then multiplying by N (remember, we discarded the remainder, so the last two steps are not a no-op). That can easily be shown to work:

- the result must be divisible by N, because the last step was a multiplication of an integer by N.
- the result must be at least as large as the starting value, because the remainder that we discard could be *at most* N-1.
- the result will be the smallest satisfying those conditions, because adding N-1 could not increase the result of the remainder-discarding division by more than 1.

Next, when N is a power of 2, the bit-masking happens to be a shortcut for the division and multiplication. Shifting left is equivalent to dividing by 2 and discarding the remainder (which gets shifted out of the number), and shifting right (with zero fill) is equivalent to multiplying by 2, so the division and multiplication steps, for N=2, are equivalent to doing that back and forth shift by one bit. That in turn is equivalent to just zeroing out that bit, which we can do with a bitmask. Similarly, for N=4, we can mask out the low two bits (don't forget the add N-1 step!), three bits for N=8 etc.



We can of course generalize this with a function:

// Pad 'value' to 2^i bytes.template <int i>inline void pad(int& value) {  int mask = (1 << i) - 1;  value = (value + mask) & ~mask;}// pad 'totalsize' to 4 bytespad<2>(totalsize);// or to 16 bytespad<4>(totalsize);

This topic is closed to new replies.

Advertisement