0

I am working on a industry safety product that requires very fast startup time. I am trying to follow an industry standard for outputting an ASCII file. In order to speed up this file formatting step, I have used #define's to create several character arrays in static memory. Here's a small section for example:

#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}
};

And here's some basic code I've been using for printing it out.

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

This works fine for generating the static char arrays, and it works fine for printing out the entire ConfigFile as a whole, but the char arrays are null-terminated, which means the end result does not meet the industry standard. It seems that the #define strings are being null-terminated by the pre-processor. Is there any way around this? Or any other methods for doing this sort of high speed operation?

jetbomber117
  • 79
  • 1
  • 7

2 Answers2

3

How about string concatenation:

#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; 
Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • 1
    You could take it a step further by modifying `TS_ComtradeConfig` to contain that concatenated string, and then change StationID, ChannelCount, etc to just be pointers into that long array (and add some size members so the proper size of each member is known). If that makes any sense. – Cornstalks Dec 12 '14 at 16:15
  • Just tested this out, worked perfectly. Thanks everyone! – jetbomber117 Dec 12 '14 at 16:22
2
for(int nIndex = 0; nIndex < sizeof(ConfigFile); nIndex++)
{
    printf("%c", ((char*)(ConfigFile.StationID))[nIndex]);
} 

I have no idea why you're printing it out like that, char by char. If there's padding in that struct, you're in for some trouble.

Why not just iterate through the members of ConfigFile and fwrite them? Replace the whole loop with:

// 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);

Not only is the code more clear (since you aren't doing your weird char pointer hack), it prints out exactly what you want. It also might be slightly more efficient, as you don't have a formatting string to process (it just does a data dump).

Cornstalks
  • 37,137
  • 18
  • 79
  • 144
  • My reasoning for printing out like that is to give a hardware comm bus a contiguous piece of memory to read. Speed was again my reasoning for this method. – jetbomber117 Dec 12 '14 at 16:04
  • 2
    @jetbomber117: I'd like to see you profile the two and see which one is faster. I'll bet the `for` loop is slower than these `fwrite`s (though I'm curious to know if I'm wrong). – Cornstalks Dec 12 '14 at 16:06
  • I agree that this would be faster in a typical file system, but this is more for an application which has limited access to a hardware bus. Repeated polling is not ideal. – jetbomber117 Dec 12 '14 at 16:09
  • 1
    @jetbomber117: I understand that. I've worked on some small systems that have quirky bottlenecks. I'd still like to see an actual comparison of speed, though. But I have another idea that I'll edit into my answer. [edit: Peter's idea was what I had in mind, except with additional offset pointers and size members so you could get each property individually as well as collectively). – Cornstalks Dec 12 '14 at 16:11