C 将uint8_t数组复制到结构
我有这个数组C 将uint8_t数组复制到结构,c,memcpy,string-literals,C,Memcpy,String Literals,我有这个数组 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
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数组
成员不是以null结尾的,printf(“%s”),
将不知道何时遇到每个字符串的结尾
这可以通过限制打印字符的数量在printf
中进行控制
例如:
printf("%.*s", (int)sizeof(foo.dateOfBirth), foo.dateOfBirth);
相当于:
printf("%.6s", food.dateOfBirth);
*
指定要打印的字符的“精度”。因此,在您的情况下,出生日期
=精度/大小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" "\0" "DOE" "\0" "010119" "\0" "M" "\0" "FOO" "\0" "BAR";
DataStructTypeDef foo;
memcpy((void *)&foo, (void *)buffer, sizeof(DataStructTypeDef));
printf("%s", foo.dateOfBirth); // Expected value 01012019
}
缓冲区看起来严重损坏,因为如果我将“\0”“010119”
放为“\0010119”
,它将以错误的方式解释转义。更好的解决方案可能是将其保持为一个,并将八进制序列完全写为\000
:
uint8_t *buffer = "JOHN\000DOE\000010119\000M\000FOO\000BAR";
在这里,每个\000
变成一个空字节,并且它不会与转义序列之一后面的010119
冲突
或者,如果我获取原始缓冲字符串“JOHN:DOE:010119:M:FOO:BAR”
,并在复制后替换所有:
,则它可以工作,如下所示:
foo.pad1 = foo.pad2 = foo.pad3 = foo.pad4 = foo.pad5 = foo.pad6 = '\0';
在
memcpy
之后添加以下内容:foo.pad1=foo.pad2=foo.pad3=foo.pad4=foo.pad5=0;
。但我希望这是练习,而不是真正工作的真正结构
uint8_t firstName[5];
而不是
uint8_t firstName[4];
不要一次复制整个缓冲区,而是一个接一个地复制元素。因为每个字段的大小是固定的,所以缓冲区开始的偏移量是固定的,这使得解析工作更容易。警告:“firstName总是由4个字符组成,lastName是3个字符,等等…”如果为false,则缺少空字符结尾的位置them@zerocoldTUN如果不以空字符结尾字符串,则假定存在by,则无法使用标准函数,因此没有printf/strcpy/strdup/…
uint8_t lastName[3];
表示lastName包含1或2个字符,然后是\0,而不是3个字符您的问题是什么?您是否知道C是如何模仿“string”的,它实际上在C中不是数据类型。您可能想了解以0
结尾的char
-数组的概念。“使用填充位”您称之为“位”事实上是一个字节
,或者更准确地说是一个单元
。注意:C中不需要强制转换,建议使用sizeof对象。简化:memcpy(&foo,buffer,sizeof foo);
易于正确编码、检查和维护。“我希望这是练习,而不是真正工作的真正结构。”有什么问题吗?@zerocoldTUN例如:1)你希望只使用名字,其中名字总是4个字母,姓氏总是3个字母?2) 您可以用1个字节作为尾随零展开firstName
和lastName
,而不是pad1
和pad2
。3) 通常使用char
array作为名称,而不是字节数组。事实上,这只是一个例子。我不处理名字和姓氏。事实上,我有一个EEPROM(内存),我用它来存储我的产品的数据。产品ID、生产日期、批号等。。。从内存读取数据会返回一个字符数组,而我是定义这些字段的人。我对每个数据使用固定长度的字段,例如:日期始终是DDMMYY,一月一日不是这样写的:1119。总是010119。所以是的:我100%确定所有字段大小都是固定的,这就是为什么我想将其直接存储到数据结构中。@zerocoldTUN:“100%确定所有字段大小都是固定的”数据中冒号(:
)的用法,尽管?@zerocoldTUN:'0'
和\0
不一样。您是否真的试图用字符串“\0”初始化标量uint8_t pad1
字段?如果否,这些字符串将在编译时自动连接成一个字符串。因此,所有这些“\0”
都转化为一个\0
。我之所以这样做,是因为如果不是这样,它会将它解释为一个不同的文本,当文本中的\0
后面紧跟着一个\0
时。知道了。我没有捕捉到字段之间缺少的,
。Re“它以错误的方式解释转义”:在C中,一个八进制转义序列有一到三个八进制数字。编译器正确地将“\001”
解释为1。零可以用“\000”
@alk指定:否,只有最后的“\0”将转换为2个空字节。连接的字符串没有额外的嵌入空字节,只有显式显示的字节。%.*s
指定要输出的最大字符数。如果在此限制之前存在空终止符,则输出将在空终止符处停止。