Gilvin
Gilvin

Reputation: 33

Printf with predefined macro concatenate with strings has format specifier in C

I'm programming in Windows and MSVC. There are two ways to write a DEBUG_PRINT statement as I know of:

printf(__FUNCTION__": Error code: %x\n", ErrorCode); 
printf("%s: Error code: %x\n", __FUNCTION__, ErrorCode);

Is it okay to concatenate predefined macro with strings like this? I don't know if predefined macro like __FUNCTION__ or __LINE__ is a legit string literal. And intuitively, seems like a dangerous way to treat strings like this in C.

And what's the difference between these two? As I used /FAcs compiler option to output the code snippet to assembly, I really can't see much of a difference.

Upvotes: 2

Views: 1827

Answers (4)

Gilvin
Gilvin

Reputation: 33

Thanks for answering. Looks like the first way is a legit literal string concatenate, it just does it in build-time, and it's faster, just space consuming.

I think I'll stick in the first way. Thanks again.

Upvotes: 0

unwind
unwind

Reputation: 399803

The former will concatenate the function name in __FUNCTION__ with the format string at compile-time. The second will format it into the output at runtime.

This assumes it's a pre-defined macro (it's not standard). MSVC has __FUNCTION__ as a proper string literal, GCC does not.

__LINE__ is supported by GCC, and expands to a decimal integer, i.e. not a string.

For performance reasons, I would suggest always using the first way when possible, i.e. when the two strings are compile-time constant. There will be a price to pay, as usual: the string pool will be larger, since each use of the macro creates a unique format string. For desktop-class systems, this is probably neglible.

Upvotes: 1

skyking
skyking

Reputation: 14360

First of all __FUNCTION__ is not in the C standard, you should probably use __func__ instead (except that microsoft has decided to skip support for that in their C compiler).

Second __FUNCTION__/__func__ "macro" is not really a macro (or at least not normally - microsoft's compiler seem to behave differently), it behaves more like a local variable and therefore it isn't a candidate for the string concatenation. You should use string formatting instead (since that will ensure that your code will become more portable).

The __LINE__ macro (is a macro), but it doesn't work well with string concatenation directly since it doesn't expand to a string - it expands to a number (which by the way can be useful in other cases). However you can use the preprocessor to stringify it (the XSTR macro will first expand it's argument and then stringify the result while STR will not expand the it's argument before stringifying it):

#define STR(x) # x
#define XSTR(x) STR(x)

printf("I'm on line #" XSTR(__LINE__));

The __FILE__ macro (which is also a macro) does expand to a string literal which plays well together with string concatenation directly.

The reason you don't see any difference is that the compiler knows what printf does and can use that for optimization. It would figure out that it doesn't need to rely on printf code to expand the %s at runtime since it can do it at compile time.

Upvotes: 2

Lundin
Lundin

Reputation: 213711

The difference is that in the 1st case the string literal gets concatenated with the format string during the compiler translation phases, while in the second case, it gets read in during run-time. So the first method is much faster.

If you know that the macro is a pre-defined string literal, I don't see anything wrong with the code.

That being said, I have no idea what __FUNCTION__ is. There is a standard C macro __func__ but it is not a string literal and should be treated like a const char array.

__LINE__ is a standard C macro that gives the source file line as an integer.

Upvotes: 0

Related Questions