将 uint8_t 数组复制到结构
Copy a uint8_t array to a struct
我有这个数组
uint8_t *buffer = "JOHN:DOE:010119:M:FOO:BAR";
我想逐字段复制到数据结构
typedef struct{
uint8_t firstName[5];
uint8_t pad1;
uint8_t lastName[4];
uint8_t pad2;
uint8_t dateOfBirth[7];
uint8_t pad3;
uint8_t genre;
uint8_t pad4;
uint8_t car[4];
uint8_t pad5;
uint8_t phone[4];
uint8_t pad6;
}DataStructTypeDef;
假设所有长度都是固定的(例如,firstName
始终由 4 个字符组成,lastName
由 3 个字符组成,等等...)
我使用了这种方法:
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
当我尝试打印 dateOfBirth
时,它显示了从 01012019 开始的整个数组,如下所示
int main(void)
{
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
printf("%s", foo.dateOfBirth); // It prints 010119:M:FOO:BAR
//printf("%s", foo.dateOfBirth); // Expected value 010119
return 0;
}
由于您正在复制的 char array
成员不是空终止的,printf("%s",
不知道何时遇到每个字符串的结尾。
这可以在 printf
中通过限制打印的字符数量来控制...
例如:
printf("%.*s", (int)sizeof(foo.dateOfBirth), foo.dateOfBirth);
等效项是:
printf("%.6s", food.dateOfBirth);
.*
指定要打印的 "precision" 个字符。所以在你的情况下,dateOfBirth
= precision/size 6.
固定结构
typedef struct {
uint8_t firstName[4];
uint8_t pad1;
uint8_t lastName[3];
uint8_t pad2;
uint8_t dateOfBirth[6];
uint8_t pad3;
uint8_t genre;
uint8_t pad4;
uint8_t car[3];
uint8_t pad5;
uint8_t phone[3];
uint8_t pad6;
}DataStructTypeDef;
这对我有用:
int main(void)
{
uint8_t *buffer = "JOHN" "[=11=]" "DOE" "[=11=]" "010119" "[=11=]" "M" "[=11=]" "FOO" "[=11=]" "BAR";
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
printf("%s", foo.dateOfBirth); // Expected value 01012019
}
缓冲区看起来乱七八糟,因为如果我将 "[=14=]" "010119"
设为 "[=15=]10119"
,它会以错误的方式解释转义。更好的解决方案可能是将其保持为一个并将八进制序列完全写为 [=16=]0
:
uint8_t *buffer = "JOHN[=12=]0DOE[=12=]0010119[=12=]0M[=12=]0FOO[=12=]0BAR";
在这里,每个 [=16=]0
都变成一个空字节,并且它不会与其中一个转义序列后面的 010119
冲突。
或者,如果我使用 "JOHN:DOE:010119:M:FOO:BAR"
的原始缓冲区字符串并在复制后替换所有 :
,它会起作用,如下所示:
foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = foo.pad6 = '[=13=]';
在 memcpy
之后添加:foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = 0;
。但我希望这是练习,而不是真正工作的真正结构。
- 修改结构
向每个字段添加一个额外的字节以容纳“\0”字符。例如使用
uint8_t firstName[5];
而不是
uint8_t firstName[4];
- 单独解析字段并以'\0'结束每个字段
与其一次性复制整个缓冲区,不如一个一个地复制元素。因为,每个字段的大小是固定的,从缓冲区开始的偏移量是固定的,这使得解析工作更容易。
我有这个数组
uint8_t *buffer = "JOHN:DOE:010119:M:FOO:BAR";
我想逐字段复制到数据结构
typedef struct{
uint8_t firstName[5];
uint8_t pad1;
uint8_t lastName[4];
uint8_t pad2;
uint8_t dateOfBirth[7];
uint8_t pad3;
uint8_t genre;
uint8_t pad4;
uint8_t car[4];
uint8_t pad5;
uint8_t phone[4];
uint8_t pad6;
}DataStructTypeDef;
假设所有长度都是固定的(例如,firstName
始终由 4 个字符组成,lastName
由 3 个字符组成,等等...)
我使用了这种方法:
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
当我尝试打印 dateOfBirth
时,它显示了从 01012019 开始的整个数组,如下所示
int main(void)
{
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
printf("%s", foo.dateOfBirth); // It prints 010119:M:FOO:BAR
//printf("%s", foo.dateOfBirth); // Expected value 010119
return 0;
}
由于您正在复制的 char array
成员不是空终止的,printf("%s",
不知道何时遇到每个字符串的结尾。
这可以在 printf
中通过限制打印的字符数量来控制...
例如:
printf("%.*s", (int)sizeof(foo.dateOfBirth), foo.dateOfBirth);
等效项是:
printf("%.6s", food.dateOfBirth);
.*
指定要打印的 "precision" 个字符。所以在你的情况下,dateOfBirth
= precision/size 6.
固定结构
typedef struct {
uint8_t firstName[4];
uint8_t pad1;
uint8_t lastName[3];
uint8_t pad2;
uint8_t dateOfBirth[6];
uint8_t pad3;
uint8_t genre;
uint8_t pad4;
uint8_t car[3];
uint8_t pad5;
uint8_t phone[3];
uint8_t pad6;
}DataStructTypeDef;
这对我有用:
int main(void)
{
uint8_t *buffer = "JOHN" "[=11=]" "DOE" "[=11=]" "010119" "[=11=]" "M" "[=11=]" "FOO" "[=11=]" "BAR";
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
printf("%s", foo.dateOfBirth); // Expected value 01012019
}
缓冲区看起来乱七八糟,因为如果我将 "[=14=]" "010119"
设为 "[=15=]10119"
,它会以错误的方式解释转义。更好的解决方案可能是将其保持为一个并将八进制序列完全写为 [=16=]0
:
uint8_t *buffer = "JOHN[=12=]0DOE[=12=]0010119[=12=]0M[=12=]0FOO[=12=]0BAR";
在这里,每个 [=16=]0
都变成一个空字节,并且它不会与其中一个转义序列后面的 010119
冲突。
或者,如果我使用 "JOHN:DOE:010119:M:FOO:BAR"
的原始缓冲区字符串并在复制后替换所有 :
,它会起作用,如下所示:
foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = foo.pad6 = '[=13=]';
在 memcpy
之后添加:foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = 0;
。但我希望这是练习,而不是真正工作的真正结构。
- 修改结构
向每个字段添加一个额外的字节以容纳“\0”字符。例如使用
uint8_t firstName[5];
而不是
uint8_t firstName[4];
- 单独解析字段并以'\0'结束每个字段
与其一次性复制整个缓冲区,不如一个一个地复制元素。因为,每个字段的大小是固定的,从缓冲区开始的偏移量是固定的,这使得解析工作更容易。