使用强制转换来访问像结构一样的字节数组?
我正在研究基于微控制器的软件项目.
该项目的一部分是二进制协议的解析器. 协议是固定的,不能更改. PC充当“主设备”并主要发送命令,这些命令必须由“从设备”即微控制器板执行. 协议数据由硬件通信接口接收,例如,UART,CAN或以太网. 在接收到帧的所有字节(4-10,取决于命令)之后,将它们存储在“uint8_t cmdBuffer [10]”类型的缓冲区中并设置标志,表示现在可以执行该命令. 我不希望有太多丑陋的操作,而是自我记录代码. >我为每个命令创建一个“typedef struct” 例: typedef struct { uint8_t commandCode; uint8_t parameter_1; uint32_t anotherParameter; uint16 oneMoreParameter; }payloadA_t; //typedefs for payloadB_t and payloadC_t,which may have different parameters void parseProtocolData(uint8_t *data,uint8_t length) { uint8_t commandToExecute; //this,in fact,just returns data[0] commandToExecute = getPayloadType(data,length); if (commandToExecute == COMMAND_A) { executeCommand_A( (payloadA_t *) data); } else if (commandToExecute == COMMAND_B) { executeCommand_B( (payloadB_t *) data); } else if (commandToExecute == COMMAND_C) { executeCommand_C( (payloadC_t *) data); } else { //error,unknown command } } 我看到两个问题: >首先,根据微控制器架构,byteorder可以是intel或motorola,用于2或4字节参数. 有很多命令(大约50个),所以我不希望将cmdBuffer作为数组访问 所以我的问题: >这种方法可以,还是只是一个肮脏的黑客? 问候, 解决方法
通常,由于填充,结构对于存储数据协议是危险的.对于可移植代码,您可能希望避免使用它们.因此,保持原始数据阵列仍然是最好的主意.您只需要根据收到的命令以不同的方式解释它.
这种情况是需要某种多态性的典型示例.不幸的是,C没有对该OO功能的内置支持,因此您必须自己创建它. 最好的方法取决于这些不同类型数据的性质.由于我不知道,我只能以这种方式提出建议,它可能适用于您的具体情况,也可能不是最佳选择: typedef enum { COMMAND_THIS,COMMAND_THAT,... // all 50 commands COMMANDS_N // a constant which is equal to the number of commands } cmd_index_t; typedef struct { uint8_t command; // the original command,can be anything cmd_index_t index; // a number 0 to 49 uint8_t data [MAX]; // the raw data } cmd_t; 然后,第一步是在收到命令后,将其转换为相应的索引. // ...receive data and place it in cmdBuffer[10],then: cmd_t cmd; cmd_create(&cmd,cmdBuffer[0],&cmdBuffer[1]); ... void cmd_create (cmd_t* cmd,uint8_t command,uint8_t* data) { cmd->command = command; memcpy(cmd->data,data,MAX); switch(command) { case THIS: cmd->index = COMMAND_THIS; break; case THAT: cmd->index = COMMAND_THAT; break; ... } } 一旦索引0到N意味着您可以实现查找表.每个这样的查找表可以是函数指针的数组,其确定数据的特定解释.例如: typedef void (*interpreter_func_t)(uint8_t* data); const interpreter_func_t interpret [COMMANDS_N] = { &interpret_this_command,&interpret_that_command,... }; 使用: interpret[cmd->index] (cmd->data); 然后,您可以为不同的任务创建类似的查找表. initialize [cmd->index] (cmd->data); interpret [cmd->index] (cmd->data); repackage [cmd->index] (cmd->data); do_stuff [cmd->index] (cmd->data); ... 对不同的体系结构使用不同的查找表.像endianess这样的东西可以在解释器函数中处理.您当然可以更改函数原型,也许您需要返回一些内容或传递更多参数等. 请注意,上述示例最适合所有命令导致相同类型的操作.如果你需要根据命令做完全不同的事情,其他方法更合适. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |