There seems to be a problem replacing arguments in strncmp (and probably any other function) with the following c macro:
#define STRING_WITH_SIZE_MINUS_ONE(x) x, sizeof(x)-1
...
if (0 == strncmp(str1, STRING_WITH_SIZE_MINUS_ONE("str2")) {
// do something
}
When building with arm-linux-gnueabihf-gcc 4.9.2 this throws the error error: macro "strncmp" requires 3 arguments, but only 2 given. Building with arm-linux-gnueabihf-gcc 8.3.0 seems to work just fine.
Obviously the whole strncmp function could be put inside of the macro and it would work just fine, but it would be really beneficial to understand why this does not compile.
From the standard draft(N3096), 7.1.4, Use of library functions
Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.1 The use of #undef to remove any macro definition will also ensure that an actual function is referred to.
In your case, strncmp is both a function and a macro in your implementation, and the macro strncmp takes 3 parameters. When expanding a function-like macro, the number of arguments is determined and matched against the macro definition before any expansion, so for a macro strncmp that takes three parameters, you have to pass exactly three arguments separated by two commas in the macro argument list, unless the comma is enclosed in parentheses. If strncmp is a macro, strncmp(str1, STRING_WITH_SIZE_MINUS_ONE("str2")) is a syntax error. The error is generated even before the definition of STRING_WITH_SIZE_MINUS_ONE is checked.
In a newer version, they may have decided to remove the macro, so it's no longer an issue. You can always suppress the macro version by adding a pair of parentheses around strncmp,
Change it to
(strncmp)(str1, STRING_WITH_SIZE_MINUS_ONE("str2"))
Side note: It should be noted that your macro only work with arrays of known sizes (arrays with compile-time constant sizes, or VLAs, but not arrays of unknown sizes like arr[]), of which string literal is a special case. If you pass a const char* to your macro, your code will compile but has UB in runtime. You may consider using strlen() instead to avoid this issue.
1This means that an implementation is required to provide an actual function for each library function, even if it also provides a macro for that function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With