C 如何获取结构中任意构件的位位置

C 如何获取结构中任意构件的位位置,c,arm,C,Arm,如何获取结构中任何成员的位位置 在示例中> typedef struct BitExamStruct_ { unsigned int v1: 3; unsigned int v2: 4; unsigned int v3: 5; unsigned int v4: 6; } BitExamStruct; 是否有任何宏可以获取任何成员(如GetBitPos(v2,BitExamStruct))的位位置 我认为编译器可能根据结构中的位长度知道成员的位置。所以我想知道我是

如何获取结构中任何成员的位位置

在示例中>

typedef struct BitExamStruct_
{
    unsigned int v1: 3;
    unsigned int v2: 4;
    unsigned int v3: 5;
    unsigned int v4: 6;
} BitExamStruct;
是否有任何宏可以获取任何成员(如GetBitPos(v2,BitExamStruct))的位位置

我认为编译器可能根据结构中的位长度知道成员的位置。所以我想知道我是否可以只使用一个简单的宏而不运行代码来获得它


提前谢谢。

据我所知,没有标准的方法可以做到这一点,但这并不意味着你找不到解决方案

下面的代码不是最漂亮的代码;识别变量在内存中“开始”的位置是一种黑客行为。请记住,根据endianess的不同,以下可能给出不同的结果:

#include <stdio.h>
#include <string.h>

typedef struct s_toto
{
  int a:2;
  int b:3;
  int c:3;    
} t_toto;

int
main()
{
  t_toto toto;
  unsigned char *c;
  int bytes;
  int bits;

  memset(&toto, 0, sizeof(t_toto));
  toto.c = 1;
  c = (unsigned char *)&toto;
  for (bytes = 0; bytes < (int)sizeof(t_toto); bytes++)
    {
      if (*c)
        break;
    }
  for (bits = 0; bits < 8; bits++)
    {
      if (*c & 0b10000000)
        break;
      *c = (*c << 1);
    }
  printf("position (bytes=%d, bits=%d): %d\n", bytes, bits, (bytes * 8) + bits);
  return 0;
}
#包括
#包括
类型定义结构s_toto
{
INTA:2;
INTB:3;
INTC:3;
}托托;
int
main()
{
托托托托;
无符号字符*c;
整数字节;
整数位;
memset(&toto,0,sizeof(t_toto));
toto.c=1;
c=(无符号字符*)&toto;
对于(字节=0;字节<(int)sizeof(t_toto);字节++)
{
如果(*c)
打破
}
用于(位=0;位<8;位++)
{
如果(*c&0b10000000)
打破

*c=(*c没有便携设备(又名标准c)方法。但是,如果你需要完全控制或者非常需要这些信息,那么位域是错误的方法。正确的解决方案是移位和掩蔽。当然,这只有在你控制源代码时才可行。

我对成员变量的命名有点困惑。位1、…、位4应该是exac吗一位的大小,或者比特1的大小应该是3位,比特2的大小应该是4位,比特3的大小应该是5位,比特4的大小应该是6位?很抱歉搞混了。它只是一个名称。比特1有3位,比特2的大小应该是4位。类似的。我更改了成员的名称。然后我相信这就是你要找的。offsetof给出的是字节偏移量而不是位offset@rwols:C11标准草案Ard n1570:7.19常见定义3宏为NULL,扩展为实现定义的NULL指针常量;offsetof(类型、成员标识符)[…](如果指定的成员是位字段,则行为未定义。)有趣。
0b10000000
表示法是C中的非标准扩展(不过,C++已将其标准化)。更重要的是,您必须有
toto.c
引用才能执行此操作,这意味着您不能一般地执行此操作。您的代码适用于
toto.c
;必须将其修改为设置
toto.b
toto.a
。但它总比没有好,这是标准提供的替代方法。Bit字段是标准C中最神秘的部分之一,几乎所有行为都是由实现定义的。
(字节*8)+位
是一个小尾端字节,大尾端位索引。我喜欢像little little一样的一致尾端编号。奖金
0b10000000
-->
1
谢谢您的评论。该工具在我的公司制作硬件寄存器的头文件。通常,我为我真正需要的位字段定义位位置。但是每次如果硬件寄存器规范发生了变化,那么您可能不关心可移植性,您可以在编译器ABI文档中找到这些信息。