Invert all bits in a structure to C

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

Structure example:

typedef struct { uint16_t mem1; uint8_t mem2; uint32_t mem3; uint8_t mem4[4]; } sample_struct; 
+6
source share
5 answers

A simple and general 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 like this:

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

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

 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 check if the optimized version really matters. This will require both a huge structure and an unreasonable number of calls. Optimization like this is rarely necessary and often erroneous.

+11
source

A 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 freely point to any writable char * object.

For greater efficiency, you should use a larger pointer, such as unsigned long * , but then you need to worry about alignment problems (from start to finish). (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++; } 
+2
source

To invert all bits, the logical operator ~ is your friend. With 96 bits in the structure, it is best to cancel (accept one compliment) each element of the structure. Here is a quick example:

 #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <limits.h> typedef struct { uint16_t mem1; uint8_t mem2; uint32_t mem3; uint8_t mem4[4]; } sample_struct; /* toggle all bits in type sample_struct */ void toggle_sample (sample_struct *a) { register unsigned char i = 0; a->mem1 = ~a->mem1; a->mem2 = ~a->mem2; a->mem3 = ~a->mem3; for (i = 0; i < 4; i++) a->mem4[i] = ~a->mem4[i]; } int main (void) { sample_struct a = {0,0,0,{0}}; unsigned i = 0; printf (" \nThe struct values with all bits '0':\n\n"); printf (" mem1 : %d\n mem2 : %d\n mem3 : %d\n", (int)a.mem1, (int)a.mem2, (int)a.mem3); for (i = 0; i < 4; i++) printf (" mem4[%d] : %u\n", i, a.mem4[i]); toggle_sample (&a); /* toggle all bits in a */ printf (" \nThe struct values with all bits '1':\n\n"); printf (" mem1 : %hu\n mem2 : %hhu\n mem3 : %u\n", (int)a.mem1, (int)a.mem2, (int)a.mem3); for (i = 0; i < 4; i++) printf (" mem4[%d] : %u\n", i, a.mem4[i]); printf ("\n"); return 0; } 

Output

 $ ./bin/struct_invert The struct values with all bits '0': mem1 : 0 mem2 : 0 mem3 : 0 mem4[0] : 0 mem4[1] : 0 mem4[2] : 0 mem4[3] : 0 The struct values with all bits '1': mem1 : 65535 mem2 : 255 mem3 : 4294967295 mem4[0] : 255 mem4[1] : 255 mem4[2] : 255 mem4[3] : 255 
+2
source

as shown here

you could do: (pseudo code)

 #define X_FIELDS \ X(uint16_t, field1, ) \ X(uint8_t, field2, ) \ X(uint32_t, field3, ) \ X(uint8_t *, field4, [4]) //define the structure, the X macro will be expanded once per field typedef struct { #define X(type, name, num) type##num name; X_FIELDS #undef X } mystruct; void flip(mystruct *aStruct) { //--- "iterate" over all the fields of the structure #define X(type, name, num) \ aStruct->name ~= aStruct->name; X_FIELDS #undef X } //--- demonstrate int main(int ac, char**av) { mystruct a = { 0, 1, 2, {1,2,3}}; flip(&a); return 0; } 
+1
source

Watch data alignment.

Structures in C, if you do not specify at the beginning of the program

 #pragma pack(1) 

aligned.

This means that something called “populating data” is happening.

And you will be surprised to see that calling sizeof in your structure does not return 11, but returns 12 :).

-1
source

Source: https://habr.com/ru/post/986593/


All Articles