【问题标题】:Looking for a better way to represent unsigned char arrays寻找一种更好的方法来表示无符号字符数组
【发布时间】:2018-10-15 14:38:07
【问题描述】:

我有一堆这样的声明:

unsigned char configurePresetDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x38, 0x0B, 0x04, 0x03, 0xF2, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3 };
unsigned char beginPresetDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x3C, 0x01, 0x04, 0x2B };
unsigned char configureDirectDelivery[] = { 0x7E, 0x01, 0x00, 0x20, 0x37, 0x02, 0X03, 0XF2, 0xD5 };
...

这些是我通过串行端口发送到设备的命令。

是否有更好的方式来表示这些?在结构或类或其他东西中?

我仅限于 C++98。

谢谢。

【问题讨论】:

  • 您可能希望更好地记录它们。
  • 一个简单的改进是将这些常量设为const
  • 实际上可能是constexpr
  • @FrançoisAndrieux 只要它们确实是常量。
  • @VittorioRomeo 不在 c++98 中

标签: c++ c++98


【解决方案1】:

如何表示命令很大程度上取决于程序要发送的命令序列。

如果你的程序是完全通用的,并且需要能够发送任何可能的字节序列,那么const unsigned char 数组(或const uint8_t,如果你想更明确一点)可能是路要走。

另一方面,如果您的协议中有一些“规则”您知道永远不会改变或需要有任何例外,那么您可以编写代码来包含/执行这些规则,而不是盲目地发送程序员提供的原始序列(并希望程序员正确输入它们)。

例如,如果您知道串行设备始终要求每个命令都以前缀 0x7E, 0x01, 0x00, 0x20 开头,那么您可以通过删除该前缀来减少重复(从而减少打错字的机会)从您的序列中添加前缀并让您的发送功能自动添加它,例如:

const unsigned char configurePresetDelivery[] = { 0x38, 0x0B, 0x04, 0x03, 0xF2, 0x40, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3 };
const unsigned char beginPresetDelivery[]     = { 0x3C, 0x01, 0x04, 0x2B };
const unsigned char configureDirectDelivery[] = { 0x37, 0x02, 0X03, 0XF2, 0xD5 };

const unsigned char prefix[] = {0x7e, 0x01, 0x00, 0x20};

void send_prefix_and_command(const unsigned char * cmdWithoutPrefix, int numBytes)
{
   send(prefix, sizeof(prefix));
   send(cmdWithoutPrefix, numBytes);
}

[...]

send_prefix_and_command(configurePresetDelivery, sizeof(configurePresetDelivery));

...并且(更进一步)如果您知道您的某些命令序列将根据运行时参数而变化,那么您可以创建一个命令而不是手动编码每个变体,生成器函数为您完成(因此将可能容易出错的生成步骤封装到单个代码位置中,因此只有一个例程需要维护/调试而不是多个例程)。例如

// This is easier to do using std::vector, so I will use it
std::vector<unsigned char> generatePresetDataCommand(unsigned char presetID, unsigned short presetValue)
{
   // I'm totally making this up just to show an example
   std::vector<unsigned char> ret;
   ret.push_back(0x66);
   ret.push_back(0x67);
   ret.push_back(presetID);
   ret.push_back((presetValue>>8)&0xFF);  // store high-bits of 16-bit value into a byte
   ret.push_back((presetValue>>0)&0xFF);  // store low-bits of 16-bit value into a byte
   return ret;
}

// Convenience wrapper-function so later code can send a vector with less typing
void send_prefix_and_command(const std::vector<unsigned char> & vec)
{
   send_prefix_and_command(&vec[0], vec.size());
}

[...]

// The payoff -- easy one-liner sending of a command with little chance of getting it wrong
send_prefix_and_command(generatePresetDataCommand(42, 32599));

【讨论】:

  • 非常感谢 Jeremy,我非常喜欢命令生成器函数的想法,我会尝试在我的代码中实现它。
猜你喜欢
  • 2017-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
相关资源
最近更新 更多