相关疑难解决方法(0)

是否有理由避免使用位域结构成员?

我早就知道C中有位字段,偶尔我会用它们来定义密集的结构:

typedef struct Message_s {
     unsigned int flag : 1;
     unsigned int channel : 4;
     unsigned int signal : 11;
} Message;
Run Code Online (Sandbox Code Playgroud)

当我阅读开源代码时,我经常会发现位掩码和位移操作,以便在手工滚动的位域中存储和检索这些信息.这是如此常见,我不认为作者不知道位字段语法,所以我想知道是否有理由通过位掩码滚动位字段并转移自己的操作而不是依赖编译器生成用于获取和设置此类位字段的代码.

c struct principles c99 bit-fields

19
推荐指数
2
解决办法
1987
查看次数

位字段可移植性

在这里读到位字段不可移植.这是否意味着下面定义位字段的代码(从这里获取的代码)无法在某些机器上编译?

如果是这样,为什么呢?

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

/* define simple structure */
struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status1;

/* define a structure with bit fields */
struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status2;

int main( )
{
   printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
   printf( "Memory size occupied by status2 : %d\n", sizeof(status2));

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

c portability bit-fields

9
推荐指数
2
解决办法
4582
查看次数

具有位域的结构的存储器布局

我有这个C结构:(代表一个IP数据报)

struct ip_dgram
{
    unsigned int ver   : 4;
    unsigned int hlen  : 4;
    unsigned int stype : 8;
    unsigned int tlen  : 16;
    unsigned int fid   : 16;
    unsigned int flags : 3;
    unsigned int foff  : 13;
    unsigned int ttl   : 8;
    unsigned int pcol  : 8;
    unsigned int chksm : 16;
    unsigned int src   : 32;
    unsigned int des   : 32;
    unsigned char opt[40];
};
Run Code Online (Sandbox Code Playgroud)

我正在为它赋值,然后以16位字打印它的内存布局,如下所示:

//prints 16 bits at a time
void print_dgram(struct ip_dgram dgram)
{ …
Run Code Online (Sandbox Code Playgroud)

c unix ip struct bit-fields

7
推荐指数
2
解决办法
1万
查看次数

将uint32变量转换为位字段 - 未定义的行为?

我有一个由微控制器制造商提供的寄存器定义,可以作为位字段处理.寄存器定义如下:

#define SCU_WDTSCON0 (*( SCU_WDTSCON0_type *) 0xf00360f0u)
Run Code Online (Sandbox Code Playgroud)

位字段定义如下所示:

typedef volatile union {
unsigned U;
int I;
struct {
    unsigned    ENDINIT  :1;    // [0:0] End-of-Initialization Control Bit
    unsigned    LCK  :1;    // [1:1] Lock Bit to Control Access to WDTxCON0
    unsigned    HPW0     :2;    // [3:2] Hardware Password 0
    unsigned    HPW1     :4;    // [7:4] Hardware Password 1
    unsigned    PW   :8;    // [15:8] User-Definable Password Field for Access to WDTxCON0
    unsigned    REL  :16;   // [31:16] Reload Value for the WDT
  } B;
} SCU_WDTSCON0_type; …
Run Code Online (Sandbox Code Playgroud)

c embedded pointers bit-fields

6
推荐指数
1
解决办法
399
查看次数

最佳常见做法 I2C 寄存器映射

只是想知道关于 C 中 I²C 寄存器映射的最佳实践是什么,或者其他人经常/更喜欢使用什么。

到目前为止,我通常做了很多定义,一个用于每个寄存器,一个用于所有位、掩码、移位等。然而,最近我看到一些驱动程序使用(可能是打包的)结构而不是定义。我认为这些是 Linux 内核模块。

反正他们会

struct i2c_sensor_fuu_registers {

    uint8_t  id;
    uint16_t big_register;
    uint8_t  another_register;
    ...

} __attribute__((packed));
Run Code Online (Sandbox Code Playgroud)

然后他们会使用 offsetof(或宏)来获取 i2c 寄存器并使用 sizeof 来读取要读取的字节数。

我发现这两种方法都有其优点:

结构方法:

  • (+) 寄存器偏移量都在逻辑上包含在结构中,而不必在定义中拼写每个寄存器。
  • (+) 条目大小使用适当大小的数据类型明确说明。
  • (-) 这不包括广泛使用的位域
  • (-) 这不考虑非字节映射的寄存器映射(例如 LM75),其中从偏移 n+0x00 读取 2 个字节,但 n+0x01 是另一个寄存器,而不是寄存器 n 的高/低字节+0x00
  • (-) 这并没有考虑到地址空间中的大间隙(例如 0x00、0x01、0x80、0xAA 处的寄存器,没有中间......)并且(我认为?)依赖编译器优化来摆脱结构.

定义方法:

  • (+) 每个寄存器及其位通常定义在一个块中,这使得找到正确的符号变得容易并依赖于命名约定。
  • (+) 透明/不知道地址空间差距。
  • (-) 每个寄存器都必须单独定义,即使没有间隙
  • (-) 因为定义往往是全局的,所以名称通常很长,用几十个长符号名称在源代码中有点乱七八糟。
  • (-) 要读取的数据大小通常是硬编码的幻数或 (end - start + 1) 样式计算,符号名称可能很长。
  • (o) 透明/不知道地图中的数据大小与地址。

基本上,我正在寻找一种更智能的方法来处理这些情况。我经常发现自己为每个寄存器和每个位键入了大量令人痛苦的长符号名称,还可能还有掩码和移位(后两个取决于数据类型),结果只使用其中的几个(但讨厌稍后重新定义丢失的符号,这就是我在一个会话中输入所有内容的原因)。不过,我注意到要读/写的字节大小大多是幻数,通常需要并排阅读数据表和源代码才能理解最基本的交互。

我想知道其他人如何处理这些情况?我在网上找到了一些例子,其中人们还在大标题中费力地输入每个寄存器、位等,但没有什么是确定的......但是,在这一点上,上述两个选项似乎都不太聪明:(

c i2c

5
推荐指数
1
解决办法
3162
查看次数

具有非连续布局的C位域元素

我正在寻找最优雅的接口上的输入来放置内存映射的寄存器接口,其中目标对象在寄存器中被分割:

union __attribute__ ((__packed__)) epsr_t {
    uint32_t storage;
    struct {
        unsigned reserved0    : 10;
        unsigned ICI_IT_2to7  :  6; // TOP HALF
        unsigned reserved1    :  8;
        unsigned T            :  1;
        unsigned ICI_IT_0to1  :  2; // BOTTOM HALF
        unsigned reserved2    :  5;
    } bits;
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,访问单个位T或任何reserved字段工作正常,但要读取或写入ICI_IT需求代码更像:

union epsr_t epsr;
// Reading:
uint8_t ici_it = (epsr.bits.ICI_IT_2to7 << 2) | epsr.bits.ICI_IT_0to1;
// Writing:
epsr.bits.ICI_IT_2to7 = ici_it >> 2;
epsr.bits.ICI_IT_0to1 = ici_it & 0x3;
Run Code Online (Sandbox Code Playgroud)

在这一点上,我已经失去了bitfield抽象试图提供的简单/便利的一大块.我考虑过宏观解决方案:

#define GET_ICI_IT(_e)      ((_e.bits.ICI_IT_2to7 << …
Run Code Online (Sandbox Code Playgroud)

c embedded struct unions bit-fields

5
推荐指数
2
解决办法
466
查看次数

Rust位域和枚举C++风格

我是一个来自C/C++的Rust初学者.首先,我尝试使用user32.MessageBox为Microsoft Windows创建一个简单的"Hello-World"程序,我偶然发现了与bitfields相关的问题.免责声明:所有代码段都是在SO编辑器中编写的,可能包含错误.

消息框中的"Hello-World"

调用该函数的UTF-16LE版本所需的合并C声明是:

enum MessageBoxResult {
    IDFAILED,
    IDOK,
    IDCANCEL,
    IDABORT,
    IDRETRY,
    IDIGNORE,
    IDYES,
    IDNO,
    IDTRYAGAIN = 10,
    IDCONTINUE
};

enum MessageBoxType {
    // Normal enumeration values.
    MB_OK,
    MB_OKCANCEL,
    MB_ABORTRETRYIGNORE,
    MB_YESNOCANCEL,
    MB_YESNO,
    MB_RETRYCANCEL,
    MB_CANCELTRYCONTINUE,

    MB_ICONERROR            = 0x10UL,
    MB_ICONQUESTION         = 0x20UL,
    MB_ICONEXCLAMATION      = 0x30UL,
    MB_ICONINFORMATION      = 0x40UL,

    MB_DEFBUTTON1           = 0x000UL,
    MB_DEFBUTTON2           = 0x100UL,
    MB_DEFBUTTON3           = 0x200UL,
    MB_DEFBUTTON4           = 0x300UL,

    MB_APPLMODAL            = 0x0000UL,
    MB_SYSTEMMODAL          = 0x1000UL,
    MB_TASKMODAL            = 0x2000UL,

    // Flag values.
    MB_HELP                 = 1UL << 14,

    MB_SETFOREGROUND        = …
Run Code Online (Sandbox Code Playgroud)

c++ winapi bitflags rust bit-fields

5
推荐指数
1
解决办法
406
查看次数

C中的Bitfields和Unions给出了问题

我正在实施无线电标准,并在结构和内存大小方面遇到了问题.在下面的例子中,我需要这个结构位于单个字节的内存中(按照无线电标准),但它目前给我2个字节的大小.经过多次挖掘后,我明白这是因为联盟的"大小"是字节而不是3位......但是还没有解决这个问题.我看过:

但似乎都没有给我一个解决方案.

有任何想法吗?

谢谢!

#ifdef WIN32
#pragma pack(push)
#pragma pack(1)
#endif

typedef struct three_bit_struct
{
    unsigned char bit_a : 1;
    unsigned char bit_b : 1;
    unsigned char bit_c : 1;
}three_bit_struct_T;


typedef union
{
    three_bit_struct_T three_bit_struct;
    unsigned char another_three_bits : 3;
}weird_union_T;


typedef struct
{
    weird_union_T problem_union; 
    unsigned char another_bit : 1;
    unsigned char reserved : 4;
}my_structure_T;


int _tmain(int argc, _TCHAR* argv[])
{
     int size;

     size = sizeof(my_structure_T);

     return 0;
}


#ifdef WIN32
#pragma pack(pop) …
Run Code Online (Sandbox Code Playgroud)

c struct unions bit-fields

3
推荐指数
1
解决办法
1234
查看次数

__LITTLE_ENDIAN_BITFIELD 和 __BIG_ENDIAN_BITFIELD?

我想知道内核编译器将如何处理不同的字节序位域:

struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8
    ihl:4,
    version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8
    version:4,
    ihl:4;
#else
    #error "Please fix <asm/byteorder.h>"
#endif
......
};
Run Code Online (Sandbox Code Playgroud)

c linux-kernel

3
推荐指数
1
解决办法
2286
查看次数

I can't manipulate bit fields in C

I wanted to implement LFSR(linear feedback shift registers) in C to generate random bits. When I try to modify an individual bit or just assign a short value to memory block, all the bits set to 1. How can I stop this from happening?

struct lfsr{
    //... 
    union{
        unsigned short ff_0 : 1;
        unsigned short ff_1 : 1;
        //... 
        unsigned short ff_f : 1;
        unsigned short ff;
    }flip_flops;
};

int main() {
    struct lfsr gen;
    gen.flip_flops.ff = 1;      //all the …
Run Code Online (Sandbox Code Playgroud)

c unions bit-fields

3
推荐指数
1
解决办法
109
查看次数

标签 统计

c ×9

bit-fields ×8

struct ×4

unions ×3

embedded ×2

bitflags ×1

c++ ×1

c99 ×1

i2c ×1

ip ×1

linux-kernel ×1

pointers ×1

portability ×1

principles ×1

rust ×1

unix ×1

winapi ×1