views:

172

answers:

2

I'm creating a function in C to convert an index value into a string, which is a verbose description of the "field" represented by the index.

So, I have a nice array with all the verbose descriptions indexed by, well the index.

To dump it into a buffer I use code like this

#define BUFFER_SIZE 40
void format_verbose(uint32_t my_index,
                    char     my_buffer[BUFFER_SIZE])
  {
    snprintf(mY_buffer, BUFFER_SIZE, "%s", MY_ARRAY[my_index].description);
  }

The problem comes for some cases I need to insert some other strings into the string when formatting it. So what I want is something like this (where the description in this case contains a %s).

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    // ...
    snprintf(mY_buffer, BUFFER_SIZE, MY_ARRAY[my_index].description,
             some_string);
  }

Our make file is set up to make this (dangerous) use of snprintf() warn, and warnings are treated as errors. So, it won't compile. I would like to turn off the warning for just this line, where although it is somewhat dangerous, I will control the string, and I can test to ensure it works with every value it's called with.

Alternatively, I would be happy to do this some other way, but I'm really not keen to use this solution

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    // ...
    snprintf(mY_buffer, BUFFER_SIZE, "%s%s%s"
    MY_ARRAY[my_index].description1, some_string,
    MY_ARRAY[my_index].description2);
  }

Because it makes my description array ugly, especially for the ones where I don't need to add extra values.

+3  A: 

GCC doesn't have the ability to turn off warnings on a line by line basis, so I suspect you are out of luck. And anyway, if your coding standards say you shouldn't be doing something, you should not be looking for ways to defeat them.

Another point, when you say:

void format_verbose(uint32_t my_index,
                    char     my_buffer[BUFFER_SIZE])

you are really wasting your time typing - it is clearer and more idiomatic to say:

void format_verbose(uint32_t my_index,
                    char     my_buffer[])

or:

void format_verbose(uint32_t my_index,
                    char     * my_buffer)
anon
+1 for your other point :)
Johannes Schaub - litb
It may be that C doesn't give any protection for the size of buffers passed in, but I don't agree that it is clearer to leave the buffer size out, when you can clearly see the code assumes it is correct. Clarity is in the eye of the beholder :-) OTH, I probably should protect myself from short buffers, either with a defined error behavior, or with an assertion.An example of the coding standard issue is type casting - we allow them to prevent compiler warnings, which makes it more obvious what is happening.
Peter
A: 

After a night of thought, I plan on manually dividing the input string up, by looking for the %s marker myself, and then sending the strings separetley into snprintf() with their own %s. For this case, where only 1 type of format string is allowed, this less onerous, however it would suck to try to completely re-implement a printf() style parser.

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    char    pre_description[BUFFER_SIZE];
    char    post_description[BUFFER_SIZE];
    int32_t offset = -1;

    find_string(MY_ARRAY[my_index].description, "%s");
    ASSERT(offset >=0, "No split location!");
    // Use offset to copy the pre and post descriptions
    // Exercise left to the reader :-)
    snprintf(mY_buffer, BUFFER_SIZE, "%s%s%s"
             pre_description, some_string, post_description);
  }
Peter
Edited to remove silly attempt to check the length of a string buffer. Of course that won't work, unless the buffer is initialized all non-zero.
Peter