【问题标题】:Bitmasking and bit manipulations with C使用 C 进行位掩码和位操作
【发布时间】:2018-03-04 00:20:24
【问题描述】:

我一直试图了解位操作如何与 C 和指针一起工作,但没有运气。这是我的问题。我在内存中有 8 个字节,需要提取前 61 位并打印。例如: 0000 0000..... 0010 0111 ,我需要提取值 32 (忽略 64 位的最后 3 位。)这在 C 中如何工作?我所拥有的只是一个指向 8 字节开头的指针。

uint_64_t* myPointer;  // already pointing to start of 8bytes

typedef struct Solve{
    uint64_t myBytes: 64; // set a field thats equal to 64 bits
}

struct Solve s1;

s1.myBytes = *myPointer>>3; //failed attempt

printf("Bytes are %" PRIu64 "\n", s1.myBytes); // just prints out 0 when should be 32

【问题讨论】:

  • 你没有展示你如何设置*myPointer的值,uint64_t myBytes: 64;是一个语法错误。您还混合了有符号和无符号类型。请发布显示问题的Minimal, Complete, and Verifiable example
  • 0000 0000..... 0010 0111 或其等效编码在哪里?
  • 如果您希望从您发布的二进制文件中得到 32,则需要屏蔽低 3 位。 val &= ~(1<<3-1);

标签: c bit-manipulation bit bitmask


【解决方案1】:

如果您要打印清除了 3 个低位的 64 位值,请获取该值并使用除最低 3 位之外的所有位掩码执行逻辑与:

uint64_t myvalue = 0x0123456789abcdefULL;
uint64_t masked_value = myvalue & 0xfffffffffffffff8ULL;

printf("Bytes are %" PRIx64 "\n", masked_value );

输出:

Bytes are 123456789abcde8

【讨论】:

    【解决方案2】:

    您需要清除 64 位变量中的低 3 位。由于您对结构字段值的操作感兴趣,因此我包含了这样的示例。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <inttypes.h>
    
    #define B(x) S_to_binary_(#x)
    
    typedef struct solve{
        u_int64_t myBytes: 64; //  field that has 64 bits
    }Solve;
    
    static inline unsigned long long S_to_binary_(const char *s)
    {
        unsigned long long i = 0;
        while (*s) {
            i <<= 1;
            i += *s++ - '0';
        }
        return i;
    }
    
    int main(void)
    {
        u_int64_t mask = ~0; // This will give you 1111...1111
        mask = mask<<3;      // This will become   1111...1000
    
        Solve * myPointer;       
    
        Solve s1;                  // declare the structure s1
        s1.myBytes = B(100111);    // init the myBytes to 38 (decimal)
    
        printf("Initial value of s1.myBytes is: %lld\n", s1.myBytes);      
    
        myPointer = & s1;          //  cannot take address of bit-field 'myBytes' directly
        myPointer->myBytes = (myPointer->myBytes & mask);   // change the value of myBytes 
    
        printf("Now     value of s1.myBytes is: %lld\n\n", s1.myBytes);    // print new value
    
        // more testing 
        uint64_t myvalue1 =  0x0123456789abcdefULL;
        uint64_t myvalue  =  B(100111);  
    
        uint64_t masked_value1 = myvalue1 & mask; // This will clear low 3 bits
        uint64_t masked_value =  myvalue & mask;  // This will clear low 3 bits
    
        printf("Bytes are: %" PRIx64 "\n", masked_value1 );
    
        printf("Value is: %lld\n", masked_value );
    
        return 0;
    }
    

    输出:

    Initial value of s1.myBytes is: 39
    Now     value of s1.myBytes is: 32
    
    Bytes are: 123456789abcde8
    Value is: 32
    

    如果这些示例解决了您的问题,请告诉我。

    【讨论】:

    • 我想你误解了我只是问我如何返回最重要的 61 位。因此,例如,如果内存中的 64 位是 0000.....0010 0111,我如何打印出值 32 并忽略 LeastSignificant 3 位
    • @tylerC 您可能还想关注机器的字节序;字节顺序。
    最近更新 更多