【问题标题】:Parsing char array efficiently in C在 C 中有效地解析 char 数组
【发布时间】:2013-12-06 08:26:06
【问题描述】:

我想有效地解析 char 数组。在c中执行此操作的正确方法是什么?我是 c 编程的新手。请指导我。

数据为 32 字节。第一个字节是版本,第二个和第三个字节是序列号,依此类推。

void parsepacket(u8_t data[]) {
    u8_t version = data[0];
    u16_t sequence_number = ?;
    u16_t error_status = ?;
    u8_t command_type = ?;
    u8_t attribute_count = ?;
    u8_t pay_load[25] = ?;
}

【问题讨论】:

  • 你应该使用struct
  • payload 顺便说一句。

标签: c++ c arrays embedded byte


【解决方案1】:

我想这就是你要找的……

void parsepacket(const u8_t data[]) {  //same as u8_t*data
        u8_t version;
        u16_t sequence_number;
        u16_t error_status;
        u8_t command_type;
        u8_t attribute_count;
        u8_t pay_load[25];
        u8_t i =0;
        version = data[i];
        i++;
        sequence_number =(u16_t)(8<<data[i] + data[i+i]);
        i+=2;
        error_status = (u16_t)(8<<data[i] + data[i+i]);
        i+=2;
        attribute_count = data[i];
        i++;
        for(int j=0;j<25;j++)
          pay_load[j] = data[i++];
    }

【讨论】:

  • 这是有效的方法吗?
  • 这假设大端字节顺序,这可能对你有用,也可能不适合你。
  • 你可以做一个 memcopy 并使用适当的指针来避免移位操作,但我认为这个想法是,如何读取数据......
【解决方案2】:

数组用于类似的数据类型,例如,您可以使用 u8_t 或 u16_t 等数据类型的数组,在这种情况下,最好将其作为对结构的引用传递给例如

typedef struct {
u8_t version;
u16_t sequence_number;
u16_t error_status;
u8_t command_type;
u8_t attribute_count;
u8_t pay_load[25];
..
} data_seq;

void parsepacket(data_seq *input) {

}

data_seq *ptr_dataseq; 使用

调用它
parsepacket(&ptr_dataseq);

【讨论】:

  • 其实我想从“data[]”或者*data中解析数据。我对代码做了一些更改。
  • 那行不通,因为缺少属性'packed';甚至在某些 CPU 架构(通常在嵌入式世界中)上,严格对齐也会阻止从非对齐地址中提取 uint16_t。
【解决方案3】:

假设您不需要制作可移植代码,您可以先尝试制作一个打包结构,根据定义,它会移除填充或对齐到每个元素的相同粒度。

在 gcc 中(您可能需要查阅工具链的开发者手册),它已完成

struct __attribute__((__packed__)) foo {
     u8_t data;
     u16_t version;
     ...
     u8_t payload[25];

 };

您可能还需要检测sizeof(struct foo) == 32 的代码(通过断言)。 这本身就有点tricky to do with preprocessor, but doable(另见评论)。

下一个问题是检查架构是否允许从非单词边界读取单词。一个线索可能是 c 编译器警告偏离严格的对齐规则,应该认真对待。

一种可能性是硬编码转换,正如已经提到的here。如果这是一个重复出现的模式,那么构建一个运行时解析器可能是值得的,例如解析。

int data(char *input, size_t input_length, const char *fmt_string, void *result)
{
   switch (*fmt_string)
   {
       case '\0':  break;
       case 'b' : 
          *result = input++; break;
       case 'w' :
          result = align_to(result, sizeof(uint16_t));
          *(uint16_t *)result = get_word(input);
          input+=sizeof(uint16_t); break;
    }
}

这将解析例如字符串“bWWbb25b”,其中大写可以选择性地表示字节顺序。

【讨论】:

  • 这里字节顺序的问题外化到函数get_word()。
【解决方案4】:

最“有效”的方法可能取决于许多因素,例如:

  • 数组中的字节顺序是否与u16_t中的字节顺序相同,
  • 目标机器是否允许字节对齐的 16 位字,
  • 您的编译器是否支持结构打包方法
  • 您希望代码的可移植性或特定于机器/编译器的程度。
  • 您是需要复制数据还是简单地使用覆盖结构重新解释数据(零复制)

大多数情况的答案已经给出。

也就是说,它只有 32 个字节 - 这真的需要多高的效率?如果它在任何情况下都能满足您的性能限制,那么您可能会更好地瞄准清晰度和可移植性而不是性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 2018-02-03
    • 2011-04-04
    • 1970-01-01
    • 2021-11-21
    相关资源
    最近更新 更多