2

I am compiling with:

gcc 4.7.2
c89

I have the macro:

#define LOG_ERR(fmt, ...)                                               \
    fprintf(stderr, "[ERROR] %s:%d: error [%s] " fmt "\n", __func__, __LINE__, strerror(errno), ##__VA_ARGS__)

And I am using it like this:

LOG_ERR("Failed to connect to message queue [ %d ]", msg_id);

The fmt has been concatenated in the fprintf statement. How is this possible?

I tried to do the same with the following below (just to test the concept), but failed with a compile error:

/* Using char array */
const char name[] = "Joe";

printf("Hello how " name " how are you today?\n");

Using constant string literal
const char *name = "Joe";

printf("Hello how " name " how are you today?\n");

Both gave me the following error:

expected ')' before name

Thanks for any suggestions!

Olivia Stork
  • 4,660
  • 5
  • 27
  • 40
ant2009
  • 27,094
  • 154
  • 411
  • 609
  • see this http://stackoverflow.com/questions/1383649/concatenating-strings-in-c-which-method-is-more-efficient – MitziMeow Dec 26 '12 at 03:46

5 Answers5

6

You need a format specifier, check out the documentation for printf

const char *name = "Joe"; // or your char array, either's fine

printf("Hello how %s how are you today?\n", name);

Your attempt:

printf("Hello how " name " how are you today?\n");

Looks a little more C++ish

cout << "Hello how " << name << "are you today?\n";
Mike
  • 47,263
  • 29
  • 113
  • 177
4

When it fails, it's because you're using variables. String literals can be concatenated by the compiler i.e. if you write "abc" "123" then the compiler will treat this as "abc123". And when you do this in the macro, the preprocessor means that this is exactly what is sent to the compiler

LOG_ERR("Failed to connect to message queue [ %d ]", msg_id);

becomes

fprintf(stderr, "[ERROR] %s:%d: error [%s] " "Failed to connect to message queue [ %d ]" "\n", myfunction, 123, strerror(errno), msg_id);

Might be worth checking out the stringizer and concatenation macros too (for the preprocessor - # and ## and I never remember which is which...)

Andrew

Raktim Biswas
  • 4,011
  • 5
  • 27
  • 32
4

Difference is that the macro is textually replacing the word fmt with your string. Putting two or more literal strings together gets you the concatenation of those strings.

"Hello " "World" "!!"
/* is the same as */
"Hello World!!"

Remember, only literal strings will do this. This does not work for variables.

Think of macros like a find/replace in your code. To illustrate, consider your macro definition -

#define LOG_ERR(fmt, ...)  \
    fprintf(stderr, "[ERROR] %s:%d: error [%s] " fmt "\n",
            __func__, __LINE__, strerror(errno), ##__VA_ARGS__)

When you use it like this -

LOG_ERR("Failed to connect to message queue [ %d ]", msg_id);

It does a textual replacement and becomes -

fprintf(stderr, "[ERROR] %s:%d: error [%s] " "Failed to connect to message queue [ %d ]" "\n",
            __func__, __LINE__, strerror(errno), msg_id)

The side-by-side strings and concatenated and voila -

fprintf(stderr, "[ERROR] %s:%d: error [%s] Failed to connect to message queue [ %d ]\n",
            __func__, __LINE__, strerror(errno), msg_id)
pyrospade
  • 7,870
  • 4
  • 36
  • 52
1

If you want to define a macro for fprintf() you may do like this which is simplest IMHO.

#define LOG_ERR(...)   fprintf(stderr, __VA_ARGS__)

and use it like

int main()
{

    int  myVar =100;

    LOG_ERR ("The value of myVar is %d", myVar); 

    return 0; 
}
Raktim Biswas
  • 4,011
  • 5
  • 27
  • 32
NeonGlow
  • 1,659
  • 4
  • 18
  • 36
0
#include <stdio.h>
#include <sys/time.h>
#include <string>

#define MyPrint(...) {\
struct timeval tv;\
gettimeofday(&tv,0);\
printf("%d.%d:", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec);\
printf(__VA_ARGS__);}
zhen liu
  • 87
  • 3
  • 2
    Please consider adding some explanation to your answer. – HMD Apr 20 '18 at 07:57
  • this idea is to add any additional actions before printf, any thing you want to be done before a printf. the demo code is to print date time and no enter sign in the end. the effect is when ever u printf, there is a timestamp ahead. – zhen liu May 07 '18 at 06:09