提问人:Bernd Klein 提问时间:10/29/2023 最后编辑:πάντα ῥεῖBernd Klein 更新时间:10/29/2023 访问量:50
Arduino (ESP32) - Struct-Size 和输出混淆
Arduino (ESP32) - Struct-Size and output obfuscated
问:
我尝试在 EPS32 上将结构转换为字节流。 在我的结构/联合下面。
#include <Arduino.h>
typedef struct {
uint16_t header;
float pi;
uint16_t crc;
} BlackBoxStruct;
typedef union {
BlackBoxStruct data;
uint8_t bytes [sizeof(BlackBoxStruct)];
} BBD;
BBD bbd;
uint8_t size, size2, size3;
char buf[100];
void setup() {
Serial.begin(115200);
bbd.data.header=0xFEEF;
bbd.data.pi = 1.234;
bbd.data.crc=0x1122;
size = sizeof(BlackBoxStruct);
size2 = sizeof(bbd);
size3 = sizeof(BBD);
sprintf(buf, "\n\nArraySize: %d, StructSize: %d, BBD: %d", size, size2, size3);
Serial.println(buf);
for (uint8_t i=0; i < size; i++) {
sprintf(buf, "byte %03d is %02x", i, bbd.bytes[i]);
Serial.println(buf);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
我仍然想知道for-loop
ArraySize: 12, StructSize: 12, BBD: 12
byte 000 is ef <= header uint16_t 2 Bytes little endian 0xFEEF
byte 001 is fe
byte 002 is 00 <== ??? - seems to be a uint16_t or 2 uint8_t
byte 003 is 00
byte 004 is b6 <== float 4 bytes
byte 005 is f3
byte 006 is 9d
byte 007 is 3f
byte 008 is 22 <== CRC, uint16_t little endian 0x1122
byte 009 is 11
byte 010 is 00 <== ??? 2 bytes
byte 011 is 00
我无法解释这 4 个标有 ??? 的字节
有什么想法吗?
我期望数组的大小为 8 字节,其他 4 个字节 - 我不知道。
这种行为更令人困惑。 我更改了我的结构并包含两个数组。
typedef struct {
uint16_t header;
long ldata[2];
float pid[2];
uint16_t crc;
} BlackBoxStruct;
和输出
ArraySize: 24, StructSize: 24, BBD: 24
byte 000 is ef
byte 001 is fe
byte 002 is 00 <== long are 4 bytes - 1. LONG
byte 003 is 00
byte 004 is 44
byte 005 is 33 <== 0x3344
byte 006 is 00 <== long are 4 bytes - 2. LONG
byte 007 is 00
byte 008 is cd
byte 009 is ab <== 0xabcd
byte 010 is 00 <== ???
byte 011 is 00 <== ???
byte 012 is b6 <== 1. float
byte 013 is f3
byte 014 is 9d
byte 015 is 3f
byte 016 is 1b <== 2. float
byte 017 is 2f
byte 018 is 5d
byte 019 is 40
byte 020 is 22 <== crc 0x1122
byte 021 is 11
byte 022 is 00 <== ???
byte 023 is 00 <== ???
答:
2赞
hcheung
10/29/2023
#1
我期望数组的大小为 8 字节,其他 4 个字节 - 我不知道。
ESP32 作为 32 位 MCU,其数据结构对齐为 4,因此即使您根据其数据类型在结构中添加所有元素,也支持为 8 字节,但为这两个元素添加了填充,使其长度为 4 字节,以便与 4 字节内联。编译器这样做既是出于性能原因,也是出于数据对齐的目的(请参阅下面的链接以获取进一步阅读)。这可以通过以下简单示例来观察。uint16_t
float
#include <Arduino.h>
typedef struct{
uint16_t head{0x1234};
float f{1000.0};
uint16_t tail{0x5678};
} Foo_t;
Foo_t foo;
void setup() {
Serial.begin(115200);
// since you are using an esp32, so Serial.printf() is available
Serial.printf("The size of uint16_t head %d bytes\n", sizeof(foo.head));
Serial.printf("The size of float f %d bytes\n", sizeof(foo.f));
Serial.printf("The size of uint16_t tail %d bytes\n", sizeof(foo.tail));
Serial.printf("The size of foo %d\n", sizeof(foo));
uint8_t *ptr = (uint8_t*) &foo;
for(int i=0; i<sizeof(foo); i++) {
Serial.printf("byte %d=%02x\n", i, *ptr++);
}
}
void loop() {
}
这将生成以下输出:
The size of uint16_t head 2 bytes
The size of float f 4 bytes
The size of uint16_t tail 2 bytes
The size of foo 12
byte 0=34 // uint16_t 0x1234 stored in little endian
byte 1=12
byte 2=00 // padding for 0x1234
byte 3=00 // padding for 0x1234
byte 4=00 // float 1000.0 stored accoding to IEEE754 as 0x447a00000
byte 5=00
byte 6=7a
byte 7=44
byte 8=78 // uint16_t 0x5678 in little endian
byte 9=56
byte 10=00 // padding
byte 11=00 // padding
现在将数据结构更改为以下内容,看看你得到了什么?
typedef struct{
uint16_t head1{0x1234};
uint16_t head2{0x5678};
float f{1000.0};
uint16_t tail{0x9abc};
} Foo_t;
或
typedef struct{
uint8_t head1{0x12};
uint16_t head2{0x5678};
float f{1000.0};
uint16_t tail{0x9abc};
} Foo_t;
所有这些结构的大小为 12 字节。
延伸阅读
评论
0赞
Bernd Klein
10/29/2023
啊,完美,谢谢你的回复。这对理解这种行为有很大帮助。
0赞
hcheung
10/30/2023
不客气,如果您认为这有帮助并回答了您的问题,请考虑通过单击此答案帖子旁边的“复选”标记来接受它作为答案。
评论