2

I am trying to add a error with the cpp to my source code, to notify who is changing it the string size it too small to handle tha data.

Suppose you have someting like

#define STRING "Hello world"

I want in a successive part of the code to have something like

#if STRING_LENGTH < MAX_STRING_LENGTH
#error "you need to extend the value of MAX_STRING_LENGTH"
#endif

So the question is: how can I define STRING_LENGTH ?

Ottavio Campana
  • 4,088
  • 5
  • 31
  • 58
  • 5
    I have to vote to close the question since it is answered [here](http://stackoverflow.com/questions/5022067/strlen-in-the-c-preprocessor). Use sizeof() which is not in the preprocessor but still resolved at compile time – Lorenzo Belli Jun 16 '16 at 07:36
  • As far as I understand, sizeof cannot be used in cpp conditionals. – Ottavio Campana Jun 16 '16 at 07:39
  • @Ottavio_Campana you are [right](http://stackoverflow.com/questions/4079243/how-can-i-use-sizeof-in-a-preprocessor-macro) – Lorenzo Belli Jun 16 '16 at 07:55

2 Answers2

3

You can't do it in the preprocessor. The best you can do is to get a compile time constant.

sizeof("string literal") - 1 will be the same as strlen("string literal")

You can then use _Static_assert from C11 to do a compile time check:

_Static_assert(sizeof(STRING) - 1 < MAX_STRING_LENGTH, "you need to extend the value of MAX_STRING_LENGTH")
Art
  • 19,807
  • 1
  • 34
  • 60
0

The C preprocessor does not provide any mechanism to get the length of a string literal.

However, with gcc/clang in C99 or C11 mode, and using the -Wall option, you can force a compiler warning by inserting something like:

static void validateSTRING(void) {
  (void)(char[MAX_STRING_LENGTH]){STRING};
}

(Note: the use of MAX_STRING_LENGTH was deliberate. If you were actually allocating an array, you would want MAX_STRING_LENGTH+1 to allow room for the NUL terminator, but here it is just trying to produce a warning and the compiler does not warn if you deliberately don't leave space for a NUL.)

rici
  • 234,347
  • 28
  • 237
  • 341
  • This method is problematic, because C has a weird special case rule that only applies to initialization from string literals: 6.7.9/14 "An array of character type may be initialized by a character string literal or UTF−8 string literal, optionally enclosed in braces. Successive bytes of the string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.". Meaning that you might not get any compiler diagnostic for this at all. So this answer is not a good recommendation. Note that C is different from C++ here. – Lundin Jun 16 '16 at 08:11
  • For example gcc is unable to give a diagnostic for `char str [5] = "hello";` where the null terminator didn't fit. – Lundin Jun 16 '16 at 08:17
  • @lundin: i neglected to say that my recommendation is to not have maximum string lengths; most of the time they are the res of unreasonable fear of malloc. So I agree that it is not a recommendation. But gcc does produce a warning; as you say, it is not an error and other compilers might not earn, but the answer specifies a particular case where it will work. – rici Jun 16 '16 at 08:17
  • See my new comment (posted at the same time as yours) for a case where gcc fails, because the code is conforming and valid C. Other C compilers may also fail to give a diagnostic where the whole string doesn't fit. The correct answer here is to use static assert, other methods are not safe or reliable. – Lundin Jun 16 '16 at 08:19
  • @lundin: and i specifically dealt with the NUL byte. If MAX_STRING_LENGTH is 5, it is reasonable to assume that "hello" is acceptable; otherwise the macro is misnamed. You need to construct the check with the real maximum string length, not the `sizeof` tbe longest string. The note at the end of the answer tries to explain that. – rici Jun 16 '16 at 08:21