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.
Related
My iprintf function repeats the same string e.g.:
iprintf("[USER] created user:%d", userID);
iprintf("[USER] user disconnected:%d, userID");
I am trying to save some space and do something like this
const char strUser[] = "[USER]";
iprintf(strUser + "created user:%d", userID);
iprintf(strUser + "user disconnected:%d", userID);
What in C language can replace the "+" so it will work?
I am trying to keep at least part of the string as a parameter.
And do it during compilation with no extra functions
If and how much space any attempt at optimization saves depends on the compiler. There is usually an option for a "minimum size build". Compiling the program and checking the results is the only method to see if space was truly saved. There is a good chance that any compiler, aiming for a minimum size build, that sees const char strUser[] = "[USER] "; will create exactly one string in the program, and point to that string wherever it is used.
Here are three options you could try. One using a macro, one using a function, and one using a different function call. I know you asked for "during compilation with no extra functions", but this function may very well be "optimized away" during compilation.
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
// warning: ISO C does not permit named variadic macros
#define IPRINTF1(format, args...) printf("[USER] " format, ##args);
// An iprintf wrapper that first prints the desired string.
void iprintf2(const char *restrict format, ...)
{
printf("[USER] ");
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
int main(void)
{
const int userID = 5;
const char strUser[] = "[USER] ";
IPRINTF1("created user:%d\n", userID);
iprintf2("created user:%d\n", userID);
// Passing the string as an additional parameter.
// This may be the best solution code quality-wise, as it avoids repetition while keeping the code dynamic.
printf("%screated user:%d\n", strUser, userID);
}
Actually concatenating two strings with + as in Python is not possible in C. Instead there is the strcat function. However, this involves allocating a buffer that is large enough, making a copy of the format string, always guaranteeing that the restrict qualifier holds... This is almost certainly not worth it.
Also, this is all under the assumption that saving a couple of bytes is worth the decrease in code quality.
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.
I have a function which returns an integer value. Now I want to write a macro which call this function, gets the return value and prepends a string to it and return the resultant string.
I have tried this:
#define TEST(x) is_enabled(x)
I call this macro in the main function as:
int ret = 0;
ret = TEST(2);
printf("PORT-%d\n", ret);
This works perfectly. However I want the macro to return the string PORT-x, where, x is the return value of the called function. How can I do this?
EDIT :
I also tried writing it into multiple lines as:
#define TEST(x)\
{\
is_enabled(x);\
}
And called it in the main function as:
printf("PORT-%d\n", TEST(2));
But this gives a compile time error:
error: expected expression before â{â token
Use a function, not a macro. There is no good reason to use a macro here.
You can solve it by using sprintf(3), in conjonction with malloc or a buffer. See Creating C formatted strings (not printing them) or man pages for details.
About your edit: You don't need to use braces {} in a macro, and they are causing your error as preprocessing would translate it to something like
printf("format%d", {
is_enabled(x);
});
To better understand macros, run gcc or clang with -E flag, or try to read this article: http://en.wikipedia.org/wiki/C_preprocessor
That's a bit of a pain since you need to ensure there's storage for the string. In all honesty, macros nowadays could be reserved for conditional compilation only.
Constants are better done with enumerated types, and macro functions are generally better as inline functions (with the knowledge that inline is a suggestion to the compiler, not a demand).
If you insist on using a macro, the storage could be done with static storage though that has problems with threads if you're using them, and delayed/multiple use of the returned string.
You could also dynamically allocate the string but then you have to free it when done, and handle out-of-memory conditions.
Perhaps the easiest way is to demand the macro user provide their own storage, along the lines of:
#include <stdio.h>
#define TEST2_STR(b,p) (sprintf(b,"PORT-%d",p),b)
int main (void) {
char buff[20];
puts (TEST2_STR(buff, 42));
return 0;
}
which outputs:
PORT-42
In case the macro seems a little confusing, it makes use of the comma operator, in which the expression (a, b) evaluates both a and b, and has a result of b.
In this case, it evaluates the sprintf (which populates the buffer) then "returns" the buffer. And, even if you think you've never seen that before, you're probably wrong:
for (i = 0, j = 9; i < 10; i++, j--)
xyzzy[i] = plugh[j];
Despite most people thinking that's a feature of for, it's very much a different construct that can be used in many different places:
int i, j, k;
i = 7, j = 4, k = 42;
while (puts("Hello, world"),sleep(1),1);
(and so on).
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.
Edit 3: For the code itself all together check the first answer or the end of this post.
As stated in the title I'm trying to find a way to tell if an optional argument was passed to a function or not. What I'm trying to do is something like how almost all dynamic languages handle their substring function. Below is mine currently, but it doesn't work since I don't know how to tell if/when the thing is used.
char *substring(char *string,unsigned int start, ...){
va_list args;
int unsigned i=0;
long end=-1;
long long length=strlen(string);
va_start(args,start);
end=va_arg(args,int);
va_end(args);
if(end==-1){
end=length;
}
char *to_string=malloc(end);
strncpy(to_string,string+start,end);
return to_string;
}
Basically I want to still be able to not include the length of the string I want back and just have it go to the end of the string. But I cannot seem to find a way to do this. Since there's also no way to know the number of arguments passed in C, that took away my first thought of this.
Edit:
new way of doing it here's the current code.
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
#define substring_defarg_2 (0)
char *substring(char *string,unsigned int start, int end){
int unsigned i=0;
int num=0;
long long length=strlen(string);
if(end==0){
end=length;
}
char *to_string=malloc(length);
strncpy(to_string,string+start,end);
return to_string;
}
and then in a file I call test.c to see if it works.
#include "functions.c"
int main(void){
printf("str:%s",substring("hello world",3,2));
printf("\nstr2:%s\n",substring("hello world",3));
return 0;
}
functions.c has an include for functions.h which includes everything that is ever needed. Here's the clang output(since clang seems to usually give a bit more detail.
In file included from ./p99/p99.h:1307:
./p99/p99_generic.h:68:16: warning: '__error__' attribute ignored
__attribute__((__error__("Invalid choice in type generic expression")))
^
test.c:4:26: error: called object type 'int' is not a function or function
pointer
printf("\nstr2:%s\n",substring("hello world",3));
^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from test.c:1:
In file included from ./functions.c:34:
In file included from ./functions.h:50:
./string.c:77:24: note: instantiated from:
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
GCC just says the object is not a function
Edit 2: Note that setting it to -1 doesn't change it either, it still throws the same thing. The compile options I'm using are as follows.
gcc -std=c99 -c test.c -o test -lm -Wall
Clang is the same thing(whether or not it works with it is another question.
ANSWER HERE
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include "p99/p99.h"
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
#define substring_defarg_2() (-1)
char *substring(char *string, size_t start, size_t len) {
size_t length = strlen(string);
if(len == SIZE_MAX){
len = length - start;
}
char *to_string = malloc(len + 1);
memcpy(to_string, string+start, len);
to_string[len] = '\0';
return to_string;
}
You will need p99 from there. It is by the selected answer. Just drop into your source directory and you should be OK. Also to summarize his answer on the license. You're able to use it however you want, but you cannot fork it basically. So for this purpose you're free to use it and the string function in any project whether proprietary or open source.
The only thing I ask is that you at least give a link back to this thread so that others who happen upon it can learn of stack overflow, as that's how I do my comments for things I've gotten help with on here.
In C, there's no such thing as an optional argument. The common idiom for situations like this is to either have two functions; substr(char *, size_t start, size_t end) and substr_f(char *, size_t start) or to have a single function where end, if given a special value, will take on a special meaning (such as in this case, possibly any number smaller than start, or simply 0).
When using varargs, you need to either use a sentinel value (such as NULL) at the end of the argument list, or pass in as an earlier argument the argc (argument count).
C has a very low amount of runtime introspection, which is a feature, not a bug.
Edit: On a related note, the correct type to use for string lengths and offsets in C is size_t. It is the only integer type that is guaranteed to be both large enough to address any character in any string, and guaranteed to be small enough to not be wasting space if stored.
Note too that it is unsigned.
Other than common belief functions with optional arguments can be implemented in C, but va_arg functions are not the right tool for such a thing. It can be implemented through va_arg macros, since there are ways to capture the number of arguments that a function receives. The whole thing is a bit tedious to explain and to implement, but you can use P99 for immediate use.
You'd have to change your function signature to something like
char *substring(char *string, unsigned int start, int end);
and invent a special code for end if it is omitted at the call side, say -1. Then with P99 you can do
#include "p99.h"
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
#define substring_defarg_2() (-1)
where you see that you declare a macro that "overloads" your function (yes this is possible, common C library implementations use this all the time) and provide the replacement with the knowledge about the number of arguments your function receives (3 in this case). For each argument for which you want to have a default value you'd then declare the second type of macro with the _defarg_N suffix, N starting at 0.
The declaration of such macros is not very pretty, but tells at least as much what is going on as the interface of a va_arg function would. The gain is on the caller ("user") side. There you now can do things like
substring("Hello", 2);
substring("Holla", 2, 2);
to your liking.
(You'd need a compiler that implements C99 for all of this.)
Edit: You can even go further than that if you don't want to implement that convention for end but want to have two distinct functions, instead. You'd implement the two functions:
char *substring2(char *string, unsigned int start);
char *substring3(char *string, unsigned int start, unsigned int end);
and then define the macro as
#define substring(...) \
P99_IF_LT(P99_NARG(__VA_ARGS__, 3)) \
(substring2(__VA_ARGS__)) \
(substring3(__VA_ARGS__))
this would then ensure that the preprocessor chooses the appropriate function call by looking at the number of arguments it receives.
Edit2: Here a better suited version of a substring function:
use the types that are semantically correct for length and stuff like
that
the third parameter seems to be a length for you and not the end of the string, name it accordingly
strncpy is almost never the correct function to chose, there are situations where it doesn't write the terminating '\0' character. When you know the size of a string use memcpy.
char *substring(char *string, size_t start, size_t len) {
size_t length = strlen(string);
if(len == SIZE_MAX){
len = length - start;
}
char *to_string = malloc(len + 1);
memcpy(to_string, string+start, len);
to_string[len] = '\0';
return to_string;
}
Unfortunately, you cannot use va_arg like that:
Notice also that va_arg does not determine either whether the retrieved argument is the last argument passed to the function (or even if it is an element past the end of that list). The function should be designed in such a way that the amount of parameters can be inferred in some way by the values of either the named parameters or the additional arguments already read.
A common "workaround" is to give the other "overload" a nice mnemonic name, such as right_substr. It will not look as fancy, but it will certainly run faster.
If duplicating implementation is your concern, you could implement left_substr, substring, and right_substr as wrappers to a hidden function that takes start and length as signed integers, and interprets negative numbers as missing parameters. It is probably not a good idea to use this "convention" in your public interface, but it would probably work fine in a private implementation.
In standard C, when using variable argument prototypes (...), there is no way to tell directly how many arguments are being passed.
Behind the scenes, functions like printf() etc assume the number of arguments based on the format string.
Other functions that take, say, a variable number of pointers, expect the list to be terminated with a NULL.
Consider using one of these techniques.