在C中反转结构中的所有位

时间:2015-05-05 19:08:02

标签: c

什么是有效的方法来反转具有不同大小的不同成员的结构的所有位?

示例结构:

typedef struct {
    uint16_t mem1;
    uint8_t mem2;
    uint32_t mem3;
    uint8_t mem4[4];
} sample_struct;

5 个答案:

答案 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 :)。