Incompatible argument type conversion using macro - c

I am trying to use a single macro argument (provided by third party) to display a string with placeholders and values of those place holder.
#define DBG1(AR1) do{ \
printf(AR1); \
}while(0);
int main()
{
int varDummy = 123;
/* Expecting Test Message 123*/
DBG1(("Test Message %d\r\n", varDummy));
return 0;
}
Notice the argument of DBG1 ("Test Message %d\r\n", varDummy) is in parentheses and is being treated whole as a string i.e. const char* and error shows up that varDummy not allowed to be converted due to it's int type.
In the actual code the argument of DBG1 has different number of place holders (%d, %x...) and respective values which have to be printed. Apparently I am unable to display the passed string along with its place holder values.
In the real code I have the following macro from third party
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags));
/* discarding the first argument */
#define LWIP_DEBUGF(debug, message) do{ \
DBG1(message) \
}while(0);
Please note this is a resource constrained embedded system.

Notice the argument of DBG1 ("Test Message %d\r\n", varDummy) is in parentheses …
This problem is at the same time the solution. Since there are already parentheses, you need not supply them in your DBG1 macro and can change printf(AR1); \ to printf AR1; \. Besides that, you can simplify the macro to
#define DBG1(AR1) printf AR1;
(since you can't change the LWIP_DEBUGF macro from third party, we unfortunately have to keep the semicolon).

You can use a temporary buffer to hold the adjointed string, something like this:
#define DBG1(AR1) do{\
printf(AR1);\
} while(0)
#define BUFFER_SIZE 100
int main()
{
int varDummy = 123;
char buffer[BUFFER_SIZE];
sprintf(buffer, "Test Message %d\r\n", varDummy);
/* Expecting Test Message 123*/
DBG1(buffer);
return 0;
}

Notice the argument of DBG1 is in parentheses
Yeah that's the problem, you are calling printf(("Test Message %d\r\n", varDummy)); where the inner parentheses has turned the , from a function argument separator into the comma operator. The comma operator discards the left operand and returns the right. Which is int, a type incompatible with the format string of printf, which explains the compiler error.
Instead you should be using a variadic macro:
#define DBG1(AR1,...) printf(AR1, __VA_ARGS__)
...
DBG1("Test Message %d\r\n", varDummy);
The do-while(0) trick is pointless to use in this case.
Please note this is a resource constrained embedded system.
Then you shouldn't be using stdio.h or variadic functions in the first place. Instead, design your own product-specific logging module. Writing a little snippet that spits out strings on UART isn't rocket science.
Similarly, parsing raw binary data from UART isn't rocket science either, so you don't actually need the string conversion, just a decent terminal program on the PC.

Related

winapi - display int variable value in MessageBox using macros

For debugging purposes I am trying to make a short macros to display various types, instead of constant copying all the MessageBox functions' params.
For strings I have following macros:
#define DEBUG(x) MessageBox(NULL, x,"DEBUG",MB_ICONINFORMATION|MB_OK);
Calling it working great, whether I pass variable (array of char) or direct string.
Now, I try to make the same thing for int. Have defined macros like this:
#define STRIGIFY(x) #x
#define TOSTRING(x) STRIGIFY(x)
#define DEBUGINT(x) DEBUG(TOSTRING(x))
It works only in case I pass direct integer value:
DEBUGINT(742);
However if I pass int variable, MessageBox displays variable name instead of its value:
int count = 3;
DEBUGINT(count);
The thing I find pretty interesting for me is that I can pass literally anything in DEBUGINT macros and it will still work:
DEBUGINT(some unescaped string)
How do I define a macros that would use a variable value instead of its name?
This doesn't answer the question as it was asked, but I'll risk my reputation and suggest a different solution.
PLEASE, do yourself a favor and never use MessageBox() or other modal UI to display debug information. If you do want to interrupt program execution at that point, use the breakpoint; it also allows you to attach the condition, so that you don't need to examine the value manually.
If you do not want the interruption, just print the value to a debug output window using ::OutputDebugString(). That can be seen in the debugger if it is attached, or via DebugView tool.
Another small suggestion (for Visual Studio users): if you prepend your output with a source file name and the code line number, double-clicking on that line in the output window will take you straight to that line. Just use __FILE__ and __LINE__ in your formatted string.
You can't. The preprocessor doesn't know anything about variables or their values, because it doesn't do anything run-time only at compile-time.
You can use variable argument list
#include <stdio.h>
void message(const char* format, ...)
{
int len;
char *buf;
va_list args;
va_start(args, format);
len = _vscprintf(format, args) + 1; //add room for terminating '\0'
buf = (char*)malloc(len * sizeof(char));
vsprintf_s(buf, len, format, args);
MessageBoxA(0,buf,"debug",0);
//OutputDebugStringA(buf);
free(buf);
}
message("test %s %d %d %d", "str", 1, 2, 3);
You might also want to change to unicode version.
You need to "print" the variable to a buffer (array of char) using something like sprintf (or snprintf in VS 2015) and pass the resulting output to MessageBox as the string to be displayed.

Using macros to convert print statements

I have multiple uses of one type of debug statement in my code - say DEBUG("abcd"); or DEBUG("abc %d def", val) which get translated and printed to a file.
Now, however I want to convert them all to a different type of logging which requires using a function with declaration like -
WRITE(char *string);
Usage: WRITE(L"abcd") etc..
Because the usage of this debug statement is huge, I am hoping to use macros to convert the same. Can this be done; also given that the DEBUG function used to take in format specifiers too?
Maybe you're looking at : #define DEBUG(str,...) WRITE(str,__VA_ARGS__)
You probably want something like the gnu function
int asprintf(char **strp, const char *fmt, ...);
that is a function that returns an allocated string of sufficiently large size in *strp that holds your printed string. Supposing that your WRITE and DEBUG macros are only used in places where they are used as statements and not inside expressions, you could then do
#define DEBUG(...) \
do { \
char* strp = 0; \
asprintf(&strp, __VA_ARG__); \
WRITE(strp); \
free(strp); \
} while(0)
If your platform doesn't have asprintf, you probably can come up with an implementation of it that uses snprintf and enlarges the string to be returned as needed.

Treating __func__ as a string literal instead of a predefined identifier

I am using gcc to compile C99 code. I want to write a macro which will return a string containing the function name and line number.
This is what I have:
#define INFO_MSG __FILE__ ":"__func__"()"
However, when I compile code which attempts to use this string, for example:
char buff[256] = {'\0'}
sprintf(buff, "Something bad happened here: %s, at line: %d", INFO_MSG, __LINE__);
printf("INFO: %s\n", buff);
I get the following error message:
error: expected ‘)’ before ‘__func__’
I have tracked the problem down to the macro. as when I remove __func__ from the macro, the code compiles correctly.
How do I fix the macro, so that I can include the predefined __func__ macro in my string?
Judging from your comments, the objective is to have a macro which combines the file name and function name (and maybe line number) into a single string that can be passed as an argument to functions such as printf() or strcpy() or syslog().
Unfortunately, I don't think that's possible.
The C11 standard says:
ISO/IEC 9899:2011 §6.4.2.2 Predefined identifiers
¶1 The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.
Therefore, __func__ is not a macro, unlike __FILE__ or __LINE__.
The related question What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__? covers some alternative names. These are GCC-specific extensions, not standard names. Moreover, the GCC 4.8.1 documentation says:
These identifiers are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used
to initialize char arrays, and they could be concatenated with other string literals. GCC
3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_FUNCTION__ have always been variables.
There are sound reasons why these cannot be preprocessor constructs. The preprocessor does not know what a function is and whether the text it is processing is in the scope of a function, or what the name of the enclosing function is. It is a simple text processor, not a compiler. Clearly, it would be possible to build that much understanding into the preprocessor (solely for the support of this one feature), but it is not required by the standard, and neither should it be required by the standard.
Unfortunately, though, I think it means that attempts to combine __func__ (by any spelling) with __FILE__ and __LINE__ in a single macro to generate a single string literal are doomed.
Clearly, you can generate the file name and line number as a string using the standard two-step macro mechanism:
#define STR(x) #x
#define STRINGIFY(x) STR(x)
#define FILE_LINE __FILE__ ":" STRINGIFY(__LINE__)
You can't get the function name into that as part of a string literal, though.
There are arguments that the file name and line number are sufficient to identify where the problem is; the function name is barely necessary. It is more cosmetic than functional, and slightly helps programmers but not other users.
After a quick experiment I found that you cannot use __func__ with stringification. It would not make much sense if you could as this would mean that the value would be wherever the macro is defined instead of where it is applied.
The nature of __func__, as noted in the comments on the question, is described in this answer.
Stringification is performed at pre-processor time and because of that __func__ is unavailable as it is essentially a function local string that is defined later on the compilation process.
However you can use __func__ in a macro as long as you don't use stringification on it. I think the following performs what you're after:
#include <stdio.h>
#define INFO_MSG "Something bad happened here: %s : %s(), at line: %d", \
__FILE__, __func__, __LINE__
int main()
{
char buff[256] = {'\0'};
sprintf(buff, INFO_MSG);
printf("INFO: %s\n", buff);
return 0;
}
Note that there's no particular reason, in the question as presented, to use a string buffer. The following main function would achieve the same effect without the possibility of buffer overrun:
int main()
{
printf("INFO: ");
printf(INFO_MSG);
printf("\n");
return 0;
}
Personally, I'd wrap up the whole process in the macro like this:
#include <stdio.h>
#define INFO_MSG(msg) printf("%s: %s : %s(), at line: %d\n", \
msg, __FILE__, __func__, __LINE__)
int main()
{
INFO_MSG("Something bad happened");
return 0;
}
Remark that, "__func__ is not a function so it cannot be called; in fact, it is a predefined identifier that points to a string that is the name of the function, and is only valid inside the scope of a function." - Jonathan.
The following is what you are looking for:
#define TO_STR_A( A ) #A
#define TO_STR( A ) TO_STR_A( A )
#define INFO_MSG TO_STR( __LINE__ ) ":" __FILE__
char buff[ 256 ] = { 0 };
sprintf( buff, "Something bad happened here, %s in function %s().", INFO_MSG, __func__ );
printf( "INFO: %s\n", buff );
... note that a call to __func__ can be made inside the function itself. See this.
it is a syntax error. I try to come over with your macro specification but I didnt find a efficient way, so maybe you can try this:
#define INFO_MSG __FILE__ , __FUNCTION__
int main()
{
char buff[256] = {'\0'};
sprintf(buff, "Something bad happened here: %s : %s(), at line: %d", INFO_MSG, __LINE__);
printf("INFO: %s\n", buff);
}

__printflike__ modifier

what is "__printflike__ modifier" exactly? what does this term mean?
At a guess it tells the compiler you're using that a function takes arguments in the form [anything, ] format, ... where the format, ... part look like the arguments to printf. The __printflike__ attribute lets the compiler test the types in the argument list against the string format. This comes up when you write a function like log(format, ...) and use vsprintf to subordinate the formatting work to the usual standard library functions before sending the string to some special log interface.
If you are using GCC then it is probably a #define in your project something like:
#define __printflike__ __attribute__((format(printf, 1, 2)))
Where 1, 2 means that format, ... appear in positions 1 and 2.
I have a function in my error reporting library with the declaration in the header like:
extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...)
PRINTFLIKE(4,5);
The PRINTFLIKE is in upper-case so that I can define it as nothing when I'm not using GCC. This use says that the first three arguments are nothing special, but the fourth argument is a format string like the ones used by printf() (indeed, internally, it gets passed to vfprintf()), and the arguments corresponding to it (formatted using the format string) start with the fifth argument.
This means that if I type:
err_logmsg(stdout, ERR_ABORT, 1, "%s: %d\n", errno, strerror(errno));
I will get a compilation error because errno is an int and strerror(errno) returns a pointer to a string. I can fix the error by changing the format string or the fifth and sixth arguments. (ERR_ABORT is a set of flags defined in the same header that declares err_logmsg().)
There are two numbers in the PRINTFLIKE macro because there could be other arguments between the format string and the first of the arguments used by the format string. For example, an alternative function could be:
extern void err_writer(FILE *fp, const char *format, int flags, int estat, ...)
PRINTFLIKE(2,5);
This tells the compiler that the format string is the second argument, but that the corresponding arguments that get formatted still appear starting at the fifth argument.
The header file for this code contains the lines:
#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN() __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN() /* If only */
#endif /* __GNUC__ */
Probably tells the compiler that the corresponding function has printf-like semantics.
This can enable the compiler to issue warnings at compile-time when the modifiers in the format string do not correspond to the type or the count of the passed arguments.
There is no other way that the compiler can have the knowledge to tell you that %u isn't the right formatting for an int when calling printf, sprintf, fprintf, etc.
I asked the reverse question a few months ago: Are printf/sprintf compiler warnings a conceptual break?

Parenthesis operator in C. What is the effect in the following code

I was playing with a macro to enable/disable traces when I came out with the following code when the macro is disabled:
int main()
{
("Hello world");
}
This code is valid and I got the desired effect (nothing happens when the macro is disabled) but I couldn't figure out what exactly is happening. Is the compiler seeing the parenthesis as a "nameless" method declaration?
To make it clearer the code is :
#ifdef TRACE
#define trace printf("%s %d -> ",__FILE__, __LINE__);printf
else
#define trace
#endif
int main()
{
trace("Hello world");
}
Thanks in advance.
If the function name is missing, as in your first example, then it is not a "parenthesis operator". It is simply a syntactic element of an expression that alters the association between operators and operands. In this case it simply does nothing. What you have is just an expression
"Hello world";
which evaluates to a value of char * type, and that value is ignored. You can surround that expression in a redundant pair of ()
("Hello world");
which will not change anything.
In exactly the same way you can write
(5 + 3);
in the middle of your code and get an expression that evaluates to value 8, which is immediately discarded.
Usually compilers generate no code for expression statements that have no side effects. In fact, in C language the result of every expression statement is discarded, so the only expression statements that "make sense" are expression statements with side effects. Compilers are normally fairly good at detecting effectless statements and discarding them (sometimes with a warning).
The warning could be annoying, so writing effectless expression statements like
"Hello world";
might not be a good idea. Typically compilers recognize a cast to void as a request not to generate this warning
(void) "Hello world";
So you might consider redefining your macro accordingly.
Of course, using the above trace technique, you have to remember that if you put something that does have a side effect as an argument for your macro
trace("%d\n", i++);
then in "disabled" form it will look as follows
("%d\n", i++);
(two subexpressions, chained by a comma operator into one expression). The side effect of incrementing i persists in this case, it does not get disabled. The whole thing is equivalent to plain
i++;
Also if you use a function call as an argument
trace(get_trace_name());
the "disabled" form will look as
(get_trace_name());
and the compiler might not be smart enough to realize that the call to get_trace_name() should be discarded. So, be careful when using your macro. Avoid arguments with side effects, avoid arguments with function calls, unless, of course, it is your intent to preserve the side effects when disabling the actual tracing.
Whether it works or not may depend on exactly what you pass as the arguments to the macro (see the side-effects issue mentioned by AndreyT). In this case it is benign. However the following is probably safer since it will result in no text being inserted when the macro is processed and TRACE is not defined:
#ifdef TRACE
#define trace printf("%s %d -> ",__FILE__, __LINE__);printf
#else
#define trace( ... )
#endif
assuming your compiler supports variadic macros. If it does the following would be a better definition perhaps:
#ifdef TRACE
#define trace( fmt, ...) printf("%s %d -> " fmt, __FILE__, __LINE__, __VA_ARGS__ ) ;
#else
#define trace( ... )
#endif
Note that the lack of a comma between "%s %d -> " and fmt is deliberate and required. Note also that the fmt argument must be a literal string constant in order for adjacent string literal concatenation to occur - a variable of any kind would generate an error, but it is bad practice to use a variable for a format specifier in any case.
("Hello world");
is an expression returning a constant pointer to a string. This value is not consumed.
Parenthesis have no specific role and you can omit them:
"Hello world";
#ifdef TRACE
#define trace printf("%s %d -> ",__FILE__, __LINE__);printf
#else
#define trace
#endif
int main {
trace("Hello world");
}
The way that macros work in C is that the compiler will (essentially)* do a literal replace of the identifier.
So in your case, there are two options depending on the value of the #IFDEF
trace("Hello world");
can become
printf("%s %d -> ",__FILE__, __LINE__);printf("Hello world");
or
("Hello world");
The first option is a sequence of valid C code which consists of two printf statements. The second option is a sequence of valid C code which consists of a string (char *) inside unnecessary braces.
If your compiler supports C99 (or you're using gcc which had this feature earlier) you can use variadic macros:
#ifdef TRACE
#define trace(...) printf("%s %d -> ",__FILE__, __LINE__);printf(__VA_ARGS__)
#else
#define trace(...)
#endif
This avoids the problems you can get with side-effects in arguments. If you have a strict C89 compiler, you've got to just avoid side-effects...

Resources