什么是有效的方法来反转具有不同大小的不同成员的结构的所有位?
示例结构:
typedef struct {
uint16_t mem1;
uint8_t mem2;
uint32_t mem3;
uint8_t mem4[4];
} sample_struct;
答案 0 :(得分:11)
一种简单而通用的方法是使用这样的函数:
void *memxor(void *p, int val, size_t size) {
unsigned char *pb = p;
while (size-- > 0) *pb++ ^= (unsigned char)val;
return p;
}
并以这种方式使用它:
sample_struct s;
...
memxor(&s, ~0, sizeof s);
如果由于某种原因,您想要优化更多,请尝试以下方法:
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;
}
}
如果优化版本确实有所作为,您可以尝试进行基准测试。它需要一个庞大的结构和一个不合理的呼叫数量。像这样的优化很少需要并经常是错误的。
答案 1 :(得分:2)
简单,便携,但不一定是最佳方式:
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];
}
这是合法的,因为您可以自由地将指向任何可写对象的指针转换为char *
。
为了提高效率,你应该使用更大的指针,比如unsigned long *
,但是你必须担心对齐问题(开始和结束)。 (并且,请注意它将不再是严格合法的C,但它会更快)。例如:
unsigned long *ptr = (unsigned long *)&the_struct;
size_t sz = sizeof(struct sample_struct) / sizeof(unsigned long);
while(sz-->0) {
*ptr = ~*ptr;
ptr++;
}
答案 2 :(得分:2)
要反转所有位,逻辑非~
运算符是您的朋友。对于结构中的96位,最好否定每个struct元素(对其进行补充)。这是一个简单的例子:
#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;
}
<强>输出强>
$ ./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
答案 3 :(得分:1)
已展示here
你可以这样做:(伪代码)
#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;
}
答案 4 :(得分:-1)
注意数据对齐。
C中的结构,除非您未在程序开始时指定
#pragma pack(1)
是对齐的。
这意味着发生了一种叫做“数据填充”的事情。
你会惊奇地发现,在你的结构上调用sizeof不会返回11而是返回12 :)。