【问题标题】:how to create pointer to a bit in c-language如何在c语言中创建指向位的指针
【发布时间】:2012-12-13 19:40:50
【问题描述】:

正如我们所知,c 语言中的 char 指针逐字节遍历内存,即每次 1 个字节, 和整数指针每次 4 字节(在 gcc 编译器中),每次 2 字节(在 TC 编译器中)。

例如:

char *cptr; // if this points to 0x100
cptr++;     // now it points to  0x101

int *iptr;  // if this points to 0x100
iptr++;     // now it points to  0x104

我的问题是:

如何在c中创建一个位指针逐位递增遍历内存?

【问题讨论】:

  • 您必须使用 C++ 来封装实现并抽象解引用运算符。你可以在 C 中做同样的事情,但你必须使用函数来模拟运算符。
  • 拥有一个指向位的指针没有任何意义,因为几乎每个(所有?)CPU 都在字节级别上工作。我听说过的每个 CPU 的地址总线都以字节表示地址。由于指针是一个地址,它必须指向一个字节,或者更大。

标签: c pointers byte bits


【解决方案1】:

char 是 C 中的“最小可寻址单元”。你不能直接指向比它更小的东西(比如一点)。

【讨论】:

    【解决方案2】:

    你不能。使用指针,不可能直接操作位。 (你真的认为糟糕的假设 bit *p = 1; p++ 会返回 1.125 吗?)

    但是,您可以使用按位运算符(例如 <<>>|&)来访问字节内的特定位。

    【讨论】:

    • 亲爱的 H2CO3 请告诉我如何使用按位运算符访问字节内的特定位,例如 >、|和&。
    • @ashrafiiqbal 例如,value & (1 << 5) 检查第 6 位是否设置在位掩码中,但您为什么不 google “C 位运算”?
    【解决方案3】:

    从概念上讲,“位指针”不是单个标量,而是由字节指针和该字节内的位索引组成的有序对。您可以使用包含两者的结构或两个单独的对象来表示它。对它们进行算术运算需要您进行一些模块化简化;例如,如果要访问给定位后 10 位的位,则必须将位索引加 10,然后以 8 为模减少,并适当地增加字节指针部分。

    顺便说一句,在只有字可寻址内存而非字节可寻址的历史系统上,char * 由字指针和字内的字节索引组成。这是完全相同的概念。不同之处在于,尽管 C 提供了char *,即使在没有字节寻址内存的机器上,它也不提供任何内置的“位指针”类型。如果需要,您必须自己创建它。

    【讨论】:

    • 这在 C++ 中甚至不会太难做到,但如果你仅限于 C,你就不能重新定义足够多的语法来让它变得更甜。
    • 呃,我可以不用句法醋。在 C 语言中以直接的方式执行它并没有什么丑陋的。
    • @R.. 解释得很好。也谢谢你的历史。
    【解决方案4】:

    没有,但是你可以写一个函数来逐位读取:

    int readBit(char *byteData, int bitOffset)
    {
       const int wholeBytes = bitOffset / 8;
       const int remainingBits = bitOffset % 8;
       return (byteData[wholeBytes] >> remainingBits) & 1;
       //or if you want most significant bit to be 0
       //return (byteData[wholeBytes] >> (7-remainingBits)) & 1;
    }
    

    用法:

    char *data = any memory you like.
    int bitPointer=0;
    int bit0 = readBit(data, bitPointer);
    bitPointer++;
    int bit1 = readBit(data, bitPointer);
    bitPointer++;
    int bit2 = readBit(data, bitPointer);
    

    当然,如果这种功能具有普遍价值,它可能已经存在。与使用位掩码和移位等相比,逐位操作效率非常低。

    【讨论】:

    • 非常感谢韦斯顿。我希望这对我有用。
    • 这是我还是评论的 MSB 变体不起作用?为了得到正确的结果,我不得不将这个班次改为第 7 部分而不是第 8 部分。所以对我来说是://return (byteData[wholeBytes] >> (7-remainingBits)) & 1;
    • @weston 哈哈谢谢。你能解释一下为什么吗?我不知道为什么我需要使用 7 而不是 8 来使其工作:O(尽管我似乎确实理解按位运算并移动一点^^)。你觉得这有意义吗?
    • @Marc 当然,remainingBits 是一个介于 0 和 7 之间的数字,因为该数字被计算为 8 的模数。我们正试图将其从 7 反转为 0。7-remainingBits 确实正是这样。
    • 如果我们使用 8,当我们得到 remainingBits 的零时,我们最终会移动 8,即整个字节都消失了。我们会超调。
    【解决方案5】:

    我认为这是不可能的,因为现代计算机是字节可寻址的,这意味着每个字节都有一个地址。所以一个位没有地址,因此指针不能指向它。您可以使用 char * 和按位运算来确定各个位的值。

    如果你真的想要它,你可以编写一个使用 char* 来跟踪内存中地址的类,一个 char(或 short/int 但是该值永远不需要高于 0000 0111 所以一个 char 会减少内存占用)以跟踪您在该字节中的哪个位,然后重载运算符,使其按您希望的方式运行。

    【讨论】:

      【解决方案6】:

      我不确定您的要求是否可行。您需要使用位移来做一些魔术来遍历指针指向的字节的所有位。

      【讨论】:

      • @ashrafiiqbal 我相信 ppl 为您提供了足够的帮助 :-) 如果您仍有问题,请尝试并发布您的 代码
      【解决方案7】:

      您总是可以将指针转换为整数,即至少比系统使用的字节指针大 3 位。然后只需将转换后的指针左移 3 位。然后将位信息存储在最低有效 3 位上。

      然后这个整数“位指针”可以用普通算术递增。

      类似这样的:

      #include <stdio.h>
      
      #define bitptr long long
      #define create_bitptr(pointer,bit) ((((bitptr)pointer)<<3)|bit) ;
      #define get_bit(bptr) ((bptr)&7)
      #define get_value(bptr)  (*((char*)((bptr)>>3))) 
      #define set_bit(bptr) get_value(bptr) |= 1<<get_bit(bptr)
      #define clear_bit(bptr) get_value(bptr) &= (~(1<<get_bit(bptr)))
      
      int main(void)
      {
          char variable=0; 
      
          bitptr p ;
          p=create_bitptr(&variable,0) ;
      
          set_bit(p) ;    p++ ; //1
          clear_bit(p) ;  p++ ; //0
          set_bit(p) ;   p++ ;  //1
          clear_bit(p) ; p++ ;  //0
          clear_bit(p) ; p++ ;  //0
          clear_bit(p) ; p++ ;  //0
          clear_bit(p) ; p++ ;  //0
          clear_bit(p) ; p++ ;  //0
      
          printf("%d\n",variable) ;
          return 0;
      }
      

      【讨论】:

        【解决方案8】:

        使用指针看起来不太可能。但是要写入或读取任何数据位,您可以试试这个。

        unsigned char data;
        
          struct _p
        
        {
        
        unsigned char B0:1;
        
        unsigned char B1:1;
        
        unsigned char B2:1;
        
        
        unsigned char B3:1;
        
        
        unsigned char B4:1;
        
        
        unsigned char B5:1;
        
        
        unsigned char B6:1;
        
        
        unsigned char B7:1;
        
        } 
        
        int main()
        
        {
        
        
        data = 15;
        
        
        _p * point = ( _p * ) & data;
        
        //you can read and write any bit of the byte with point->BX; ( Ex: printf( "%d" , point->B0;point->B5 = 1;
        
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-03
          • 2013-06-27
          • 2019-03-19
          • 1970-01-01
          • 2013-06-09
          • 1970-01-01
          相关资源
          最近更新 更多