我们有这样的例子:
struct X {
int e0 : 6;
int e1 : 6;
int e2 : 6;
...
int e10 : 6;
};
struct X c;
Run Code Online (Sandbox Code Playgroud)
如何“自动”访问成员,例如:
ce{0-10}?
假设我想读取 c.e0,然后 c.e1 ...
如果我的结构有 1000 个元素,我认为我不应该编写这么多代码,对吗?
你能帮我想一个解决方法、一个想法吗?
我提到我已经阅读了与此问题相关的其他帖子,但我没有找到解决方案。
非常感谢 !
我想从32位寄存器中读取第2位、第5位和第6位。我决定使用结构位字段来存储它们。下面的数据结构正确吗?
struct readData
{
int unwanted:1;
int reqbit1:1;
int unwanted1:2;
int reqbit2:2;
int unwanted2:26;
};
Run Code Online (Sandbox Code Playgroud)
我不确定如何创建位字段。我将使用一个 API 将字节从 h/w 寄存器直接复制到该结构。在这种情况下,reqbit1 会包含第 2 位吗?根据我的理解,编译器将第一位分配给 int 变量,第二位分配给另一个 int 变量,因此 reqbit1 不会从寄存器读取任何数据。下面的union不是更适合这种情况吗?
union readData
{
struct readBits
{
bool unwanted:1;
bool reqbit1:1;
xxx unwanted1:2;
short reqbit2:2;
xxx unwanted2:26;
};
int regValue;
};
Run Code Online (Sandbox Code Playgroud)
如果这是正确的,我应该将unknown2声明为什么?
我有以下代码:
#include <stdio.h>
#include <stdint.h>
enum nums {
ONE,
TWO,
TWENTY = 20
};
struct field {
uint32_t something : 4;
uint32_t rest : 28;
};
int main(void) {
struct field f;
f.something = TWENTY;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在运行 RTEMS 4.9.1 的 powerpc 8241 上,使用 minGW GCC 3.4.5(我知道它很旧)编译,此代码将导致段错误。我确定的原因是我们将一个数字设置为大,以便由相关位字段的位字段表示。由于我们有 4 位,它应该只能表示 0 -> 15,事实上,当我们用这些数字设置它时,它工作得很好。任何上面的东西都会崩溃。我无法在这里重现这种行为,所以我的问题是:
这是未定义的行为吗?如果是这样,交流标准中是否有涵盖它的参考文献?
或者它更可能只是因为我们非常旧的编译器而导致的错误?
我在 C 课程中被分配了以下作业:
我已经实现了解码8 字节长的 int 131809282883593 的分配,如下所示:
#include <stdio.h>
#include <string.h>
struct Message {
unsigned int hour : 5;
unsigned int minutes : 6;
unsigned int seconds : 6;
unsigned int day : 5;
unsigned int month : 4;
unsigned int year : 12;
unsigned long long int code : 26;
}; // 64 bit in total
union Msgdecode {
long long int datablob;
struct Message elems;
};
int main(void) {
long long int datablob = 131809282883593;
union …Run Code Online (Sandbox Code Playgroud) 我对bittorrent中的位字段消息有点困惑。我已经注意到下面问题形式的混乱。
握手序列完成后立即发送的位字段
我假设这是强制性的,即握手后必须遵循位字段消息。正确的?
位域消息只能在握手序列完成后、发送任何其他消息之前立即发送
假设我清楚地阅读了此消息,尽管它是可选消息。对等方仍然可以在任何消息(如请求、choke、uncoke 等)之前广播位字段消息。正确的 ?
如果我是正确的,位字段代表状态,即对等方是否拥有给定的块。
假设我的位域是[1,1,1,1,1,1,1,1,1,1 ..]. 我确定对等点丢失了第 10 块,如果位字段看起来像这样,[1,1,0,1,1,1,1,1,1,1 ..]则对等点丢失了第 3 块。那么第一个字节的高位对应的片索引0意味着什么。
末尾的备用位设置为零
这是什么意思 ?我的意思是,如果末尾有一个位为 0,并不意味着同行将其作为缺失的部分。为什么使用备用位。
我对此的预感是,位字段可以更轻松地找到合适的对等点,以了解对等点可用的信息,但我对此是否正确?
@Encombe
这是我的位字段有效负载的样子
\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF \xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE
当在 C 中使用位字段时,我发现了与用于声明字段的实际类型相关的意想不到的差异。
我没有找到任何明确的解释。现在,问题已经确定,因此,尽管没有明确的回应,但这篇文章可能对面临同样问题的任何人都有用。不过,如果有人能给出正式的解释,那就太好了。
以下结构在内存中占用 2 个字节。
struct {
char field0 : 1; // 1 bit - bit 0
char field1 : 2; // 2 bits - bits 2 down to 1
char field2 ; // 8 bits - bits 15 down to 8
} reg0;
Run Code Online (Sandbox Code Playgroud)
这个占用内存4个字节,问题是为什么?
struct {
int field0 : 1; // 1 bit - bit 0
int field1 : 2; // 2 bits - bits 2 down to 1
char field2 ; // 8 bits - bits …Run Code Online (Sandbox Code Playgroud) 我们有通过串行(蓝牙)传入的数据,它映射到特定的结构。该结构的某些部分是子字节大小,因此“显而易见”的解决方案是将传入数据映射到位字段。我无法确定的是机器或编译器的位字节顺序是否会影响它(这很难测试),以及我是否应该完全放弃位字段。
例如,我们有一条1.5字节的数据,所以我们使用结构体:
{
uint8_t data1; // lsb
uint8_t data2:4; // msb
uint8_t reserved:4;
} Data;
Run Code Online (Sandbox Code Playgroud)
保留位始终为 1
例如,如果传入的数据是 0xD2,0xF4,则值为 0x04D2,即 1234。
我们使用的结构始终适用于我们测试过的系统,但我们需要它尽可能可移植。
我的问题是:
data1无论字节序如何,总是会按预期表示正确的值(我假设是的,并且硬件/软件接口应该始终正确处理单个整个字节 - 如果发送 0xD2,则应该接收 0xD2)?
是否可能data2是reserved错误的方式,用data2代表高 4 位而不是低 4 位?
如果是:
位字节顺序(通常)是否取决于字节字节顺序,或者它们可以完全不同吗?
位字节顺序是由硬件还是编译器决定的?看起来 Intel 上的所有 Linux 系统都是一样的——对于 ARM 来说也是如此吗?(如果我们可以说我们可以支持所有 Intel 和 ARM linux 版本,那应该没问题)
是否有一种简单的方法可以在编译器中确定它的方式,并在需要时保留位字段条目?
虽然位字段是映射传入数据的最简洁的代码方式,但我想我只是想知道放弃它们并使用类似的东西是否更安全:
struct {
uint8_t data1; // lsb (0xFF)
uint8_t data2; // msb (0x0F) & reserved (0xF0)
} Data;
Data d;
int value = (d.data2 & …Run Code Online (Sandbox Code Playgroud) 我遇到了关于 C++20 位字段初始化https://en.cppreference.com/w/cpp/language/bit_field#Cpp20_Default_member_initializers_for_bit_fields 的页面,其中对于 C++20 存在以下示例(此处简化):
struct S {
int z : 1 || new int { 0 };
};
Run Code Online (Sandbox Code Playgroud)
该页面没有解释构造|| new int。这里有动态分配new int吗?的默认值z是{0}多少,是吗?你能澄清一下吗?
我想使用易失性位字段结构来设置硬件寄存器,如以下代码
union foo {
uint32_t value;
struct {
uint32_t x : 1;
uint32_t y : 3;
uint32_t z : 28;
};
};
union foo f = {0};
int main()
{
volatile union foo *f_ptr = &f;
//union foo tmp;
*f_ptr = (union foo) {
.x = 1,
.y = 7,
.z = 10,
};
//*f_ptr = tmp;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器会将其多次写入STR、LDR HW 寄存器。可怕的是,当寄存器被写入时,它会立即触发硬件工作。
main:
@ args = 0, pretend = 0, frame = 0
@ frame_needed …Run Code Online (Sandbox Code Playgroud) 这里有一个struct。
struct {
unsigned int a : 8;
unsigned int : 0;
unsigned int f : 1;
} A;
Run Code Online (Sandbox Code Playgroud)
sizeof这里的structA是8个字节。我明白那个。但现在如果我在接下来再放置一个宽度为零的未命名字段,如下所示,
struct {
unsigned int a : 8;
unsigned int : 0;
unsigned int : 0;
unsigned int f : 1;
} A;
Run Code Online (Sandbox Code Playgroud)
现在,sizeofstructA仍然是 8 个字节。当我看到引用时,它说使用未命名的字段宽度 0 强制下一个字段与下一个整数对齐。所以,这里的sizeof结构体A应该是 12 个字节。或者将两个连续的未命名字段宽度设置为 0 是否不会达到预期的效果?
bit-fields ×10
c ×7
c++ ×2
unions ×2
assembly ×1
bit ×1
bittorrent ×1
c++20 ×1
embedded ×1
endianness ×1
sizeof ×1
struct ×1
volatile ×1