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?

18
  • 3
    Did you try: const char StationID[sizeof(COMTRADE_STATION_ID)-1]; Commented Dec 12, 2014 at 15:46
  • 4
    @Rob Please refrain from advising people to overflow buffers. Everyone else, please refrain from upvoting comments advising people to overflow buffers. Commented Dec 12, 2014 at 15:48
  • 1
    @Rob: Yeah overflowing arrays is fun Commented Dec 12, 2014 at 15:48
  • 2
    "It seems that the #define strings are being null-terminated by the pre-processor" Yes, string literals are null-terminated. It doesn't have all that much to do with the #define, though... Commented Dec 12, 2014 at 15:48
  • 2
    This question is unclear. Is the output the problem, or the layout/contents of the struct? What else will you be doing with it? Which "industry standard" are you attempting to adhere to? Commented Dec 12, 2014 at 15:49

2 Answers 2

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; 
Sign up to request clarification or add additional context in comments.

2 Comments

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.
Just tested this out, worked perfectly. Thanks everyone!
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).

4 Comments

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: 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 fwrites (though I'm curious to know if I'm wrong).
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: 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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.