55

For example, how to avoid writing the 'func_name' twice?

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME "func_name"
#endif

I'd like to follow the Single Point of Truth rule.

Version of C preprocessor:

$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Brian Tompsett - 汤莱恩
  • 5,438
  • 68
  • 55
  • 126
jfs
  • 374,366
  • 172
  • 933
  • 1,594

4 Answers4

83

He who is Shy* gave you the germ of an answer, but only the germ. The basic technique for converting a value into a string in the C pre-processor is indeed via the '#' operator, but a simple transliteration of the proposed solution gets a compilation error:

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

#include <stdio.h>
int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

The syntax error is on the 'puts()' line - the problem is a 'stray #' in the source.

In section 6.10.3.2 of the C standard, 'The # operator', it says:

Each # preprocessing token in the replacement list for a function-like macro shall be followed by a parameter as the next preprocessing token in the replacement list.

The trouble is that you can convert macro arguments to strings -- but you can't convert random items that are not macro arguments.

So, to achieve the effect you are after, you most certainly have to do some extra work.

#define FUNCTION_NAME(name) #name
#define TEST_FUNC_NAME  FUNCTION_NAME(test_func)

#include <stdio.h>

int main(void)
{
    puts(TEST_FUNC_NAME);
    return(0);
}

I'm not completely clear on how you plan to use the macros, and how you plan to avoid repetition altogether. This slightly more elaborate example might be more informative. The use of a macro equivalent to STR_VALUE is an idiom that is necessary to get the desired result.

#define STR_VALUE(arg)      #arg
#define FUNCTION_NAME(name) STR_VALUE(name)

#define TEST_FUNC      test_func
#define TEST_FUNC_NAME FUNCTION_NAME(TEST_FUNC)

#include <stdio.h>

static void TEST_FUNC(void)
{
    printf("In function %s\n", TEST_FUNC_NAME);
}

int main(void)
{
    puts(TEST_FUNC_NAME);
    TEST_FUNC();
    return(0);
}

* At the time when this answer was first written, shoosh's name used 'Shy' as part of the name.

Community
  • 1
  • 1
Jonathan Leffler
  • 698,132
  • 130
  • 858
  • 1,229
  • It works. Thank you. I've posted a working example which reflects the motivation for the code. http://stackoverflow.com/questions/195975/how-to-make-a-char-string-from-a-c-macros-value#196093 – jfs Oct 12 '08 at 21:13
  • Almost verbatim rewrite of a comment originally made 2012-10-12 21:37 (which showed a bold __func__ instead of `__func__`) — Of course, in C99, we could use the `__func__` pre-defined identifier in the function to mean the function name. However, that is no help outside the function, and that's where the function name string is really needed. – Jonathan Leffler Dec 29 '13 at 18:17
  • your second code doesn't work for me. The `test_func` should be a macro for OP's case I think. If you put #define test_func my_test_func. (thus making test_func a macro), it still prints `test_func` not `my_test_func`. – Chan Kim Nov 06 '17 at 01:31
  • @ChanKim: Can you show what doesn't work? If need be (if it won't fit sanely into a comment), contact me by email — see my profile. – Jonathan Leffler Nov 06 '17 at 07:29
  • @JonathanLeffler Hi, I sent you an email. we need two level macro substitution. see https://stackoverflow.com/questions/3419332/c-preprocessor-stringify-the-result-of-a-macro – Chan Kim Nov 07 '17 at 02:00
20

@Jonathan Leffler: Thank you. Your solution works.

A complete working example:

/** compile-time dispatch 

   $ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
*/
#include <stdio.h>

#define QUOTE(name) #name
#define STR(macro) QUOTE(macro)

#ifndef TEST_FUN
#  define TEST_FUN some_func
#endif

#define TEST_FUN_NAME STR(TEST_FUN)

void some_func(void)
{
  printf("some_func() called\n");
}

void another_func(void)
{
  printf("do something else\n");
}

int main(void)
{
  TEST_FUN();
  printf("TEST_FUN_NAME=%s\n", TEST_FUN_NAME);
  return 0;
}

Example:

$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
do something else
TEST_FUN_NAME=another_func
jfs
  • 374,366
  • 172
  • 933
  • 1,594
0
#include <stdio.h>

#define QUOTEME(x) #x

#ifndef TEST_FUN
#  define TEST_FUN func_name
#  define TEST_FUN_NAME QUOTEME(TEST_FUN)
#endif

int main(void)
{
    puts(TEST_FUN_NAME);
    return 0;
}

Reference: Wikipedia's C preprocessor page

Jason Weathered
  • 7,674
  • 2
  • 39
  • 37
-1

#define TEST_FUN_NAME #FUNC_NAME

see here

shoosh
  • 73,722
  • 51
  • 204
  • 318
  • 2
    This is indeed incorrect - see also my answer. It is also amazing that it has 4 up votes. The trouble is, it looks like it might be more or less correct, if you aren't thinking carefully. – Jonathan Leffler Oct 12 '08 at 20:36