Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invert all bits in a structure in C

Tags:

c

What would be an efficient way to invert all the bits of a structure having various members of different sizes?

Sample struct:

typedef struct {
    uint16_t mem1;
    uint8_t mem2;
    uint32_t mem3;
    uint8_t mem4[4];
} sample_struct;
like image 360
Akeel Avatar asked May 05 '15 19:05

Akeel


2 Answers

A simple and generic way would be to use a function like this:

void *memxor(void *p, int val, size_t size) {
    unsigned char *pb = p;
    while (size-- > 0) *pb++ ^= (unsigned char)val;
    return p;
}

And use it this way:

sample_struct s;
...
memxor(&s, ~0, sizeof s);

If for some reason, you want to optimize more, try this:

void meminvert(void *ptr, size_t size) {
    if (((uinptr_t)ptr | size) & (sizeof(unsigned int) - 1)) {
        unsigned char *p = ptr, *pe = pb + size;
        while (p < pe) *p++ ^= ~0U;
    } else {
        unsigned int *p = ptr, *pe = p + size / sizeof *p;
        while (p < pe) *p++ ^= ~0U;
   }
}

You can try and benchmark if the optimized version actually makes a difference. It would take both a huge structure and an unreasonable number of calls. Optimisation like this is rarely needed and often erroneous.

like image 97
chqrlie Avatar answered Nov 13 '22 12:11

chqrlie


Simple, portable, but not necessarily optimal way:

char *ptr = (char *)&the_struct;
size_t sz = sizeof(struct sample_struct);
size_t i;
for(i=0; i<sz; i++) {
    ptr[i] = ~ptr[i];
}

This is legal because you can cast a pointer to any writable object to char * freely.

For more efficiency, you should use a larger pointer, like unsigned long *, but then you have to worry about alignment issues (of the start and end). (And, note that it will no longer be strictly legal C, but it will be faster). Example:

unsigned long *ptr = (unsigned long *)&the_struct;
size_t sz = sizeof(struct sample_struct) / sizeof(unsigned long);
while(sz-->0) {
    *ptr = ~*ptr;
    ptr++;
}
like image 22
nneonneo Avatar answered Nov 13 '22 12:11

nneonneo