C++ manual padding for alignment
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!
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:
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
Popular Topics
Advertisement