【问题标题】:#define a char array without null termination in C++#在 C++ 中定义一个不带空终止的 char 数组
【发布时间】:2015-02-11 08:46:03
【问题描述】:

我正在开发一种需要非常快的启动时间的行业安全产品。我正在尝试遵循输出 ASCII 文件的行业标准。为了加快这个文件格式化步骤,我使用#define's 在静态内存中创建了几个字符数组。下面是一小部分的例子:

#define COMTRADE_STATION_ID         "Station Name,Device ID,1999\r\n"
#define COMTRADE_CHANNEL_COUNT      "10,10A,0D\r\n"
#define COMTRADE_FREQUENCY          "60\r\n"
#define COMTRADE_FILE_TYPE          "BINARY\r\n1\r\n"

struct TS_ComtradeConfig
{
    const char StationID[sizeof(COMTRADE_STATION_ID)];
    const char ChannelCount[sizeof(COMTRADE_CHANNEL_COUNT)];
    char Frequency[sizeof(COMTRADE_FREQUENCY)];
    const char FileType[sizeof(COMTRADE_FILE_TYPE)];
};

TS_ComtradeConfig ConfigFile =
{
        {COMTRADE_STATION_ID},
        {COMTRADE_CHANNEL_COUNT},
        {COMTRADE_FREQUENCY},
        {COMTRADE_FILE_TYPE}
};

这是我用来打印它的一些基本代码。

for(int nIndex = 0; nIndex < sizeof(ConfigFile); nIndex++)
{
    printf("%c", ((char*)(ConfigFile.StationID))[nIndex]);
}

这可以很好地生成静态字符数组,并且可以很好地打印整个 ConfigFile 作为一个整体,但是字符数组是以空结尾的,这意味着最终结果不符合行业标准。似乎#define 字符串被预处理器以空值终止。有没有办法解决?或者有其他方法可以进行这种高速操作吗?

【问题讨论】:

  • 你试过了吗:const char StationID[sizeof(COMTRADE_STATION_ID)-1];
  • @Rob 请不要建议人们溢出缓冲区。其他所有人,请不要赞成 cmets 建议人们溢出缓冲区。
  • @Rob:是啊,溢出数组很有趣
  • “似乎#define 字符串被预处理器以空值结尾” 是的,字符串文字是以空值结尾的。不过,它与#define 并没有太大关系……
  • 这个问题不清楚。输出是问题,还是结构的布局/内容?你还会用它做什么?您试图遵守哪个“行业标准”?

标签: c++


【解决方案1】:

字符串连接怎么样:

#define COMTRADE_STATION_ID         "Station Name,Device ID,1999\r\n"
#define COMTRADE_CHANNEL_COUNT      "10,10A,0D\r\n"
#define COMTRADE_FREQUENCY          "60\r\n"
#define COMTRADE_FILE_TYPE          "BINARY\r\n1\r\n"

#define COMTRADE_ALL COMTRADE_STATION_ID COMTRADE_CHANNEL_COUNT COMTRADE_FREQUENCY COMTRADE_FILE_TYPE

    // no struct, plain char array, no intervening nulls (but a trailing one)
char[sizeof(COMTRADE_ALL)] comTradeAll = COMTRADE_ALL; 

【讨论】:

  • 您可以更进一步,修改 TS_ComtradeConfig 以包含该串联字符串,然后将 StationID、ChannelCount 等更改为指向该长数组的指针(并添加一些大小成员,以便每个成员的适当大小是已知的)。如果这有任何意义。
  • 刚刚测试过,效果很好。谢谢大家!
【解决方案2】:
for(int nIndex = 0; nIndex < sizeof(ConfigFile); nIndex++)
{
    printf("%c", ((char*)(ConfigFile.StationID))[nIndex]);
} 

我不知道你为什么要这样打印出来,charchar。如果该结构中有填充,那么您就有麻烦了。

为什么不只遍历ConfigFilefwrite 的成员呢?将整个循环替换为:

// Add a -1 to the size to skip the \0
fwrite(ConfigFile.StationID, sizeof(ConfigFile.StationID) - 1, 1, stdout);
fwrite(ConfigFile.ChannelCount, sizeof(ConfigFile.ChannelCount) - 1, 1, stdout);
fwrite(ConfigFile.Frequency, sizeof(ConfigFile.Frequency) - 1, 1, stdout);
fwrite(ConfigFile.FileType, sizeof(ConfigFile.FileType) - , 1, stdout);

不仅代码更清晰(因为您没有进行奇怪的 char 指针破解),它还准确地打印出您想要的内容。它也可能更有效,因为您没有要处理的格式化字符串(它只是进行数据转储)。

【讨论】:

  • 我这样打印的原因是给硬件通信总线一个连续的内存来读取。速度再次成为我采用这种方法的理由。
  • @jetbomber117:我想看看你对这两者的描述,看看哪一个更快。我敢打赌for 循环比这些fwrites 慢(尽管我很想知道我是否错了)。
  • 我同意这在典型的文件系统中会更快,但这更适用于对硬件总线访问受限的应用程序。重复轮询并不理想。
  • @jetbomber117:我明白这一点。我曾在一些有古怪瓶颈的小型系统上工作过。不过,我仍然希望看到速度的实际比较。但我有另一个想法,我会编辑到我的答案中。 [编辑:彼得的想法是我的想法,除了额外的偏移指针和大小成员,这样你就可以单独和集体获取每个属性。
猜你喜欢
  • 2012-04-20
  • 2016-01-22
  • 2012-03-06
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 2012-01-10
  • 1970-01-01
  • 2016-01-13
相关资源
最近更新 更多