There is no direct way to get the 'bitwise not' of an entire structure in one operation. You would probably need to do a member-wise evaluation of the structure, unless you wrote a function analogous to memset()
:
void memnot(void *data, size_t length)
{
unsigned char *src = (unsigned char *)data;
while (length-- > 0)
*src = ~*src;
}
Your macro would then need to be one of:
#define BITWISE_INVERT_STRUCT(x) memnot(&(x), sizeof(x))
#define BITWISE_INVERT_STRUCTPTR(x) memnot(x, sizeof(*(x)))
If this proves to be a bottleneck, you can consider optimizing. For example, if length is a multiple of 8 bytes, then use a loop on uint64_t
; if it is a multiple of 4 bytes, then use a loop on uint32_t
; if it is a multiple of 2 bytes, then use a loop on uint16_t
; else use what is shown here. This makes the possibly radical assumption that if a structure is a multiple of 8 bytes long, then valid structure addresses will also be on a multiple of 8 bytes. This is not necessarily the case; a structure such as struct irksome { uint16_t a, b, c, d; };
only requires a 2-byte alignment even though it is 8 bytes long. You can do other, more careful/subtle analyses of the address and size and decide whether to do things byte-wise or in larger multiples.
The name memnot()
is reserved to the implementation (C99 §7.26.11 - Future directions for <string.h>
).
Function names that begin with str, mem, or wcs and a lowercase letter may be added
to the declarations in the header.
You might prefer to use mem_not()
or memNot()
or something else as the function name.