Подтвердить что ты не робот

Как сделать строку char из значения макроса C?

Например, как избежать двукратного написания "func_name"?

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

Я хотел бы следовать правилу Single Point of Truth.

Версия препроцессора C:

$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
4b9b3361

Ответ 1

Тот, кто застенчив * дал вам зародыш , но только зародыш. Основной метод преобразования значения в строку в предварительном процессоре C действительно осуществляется с помощью оператора "#", но простая транслитерация предлагаемого решения получает ошибку компиляции:

#define TEST_FUNC test_func
#define TEST_FUNC_NAME #TEST_FUNC

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

Синтаксическая ошибка находится в строке 'puts()' - проблема заключается в "случайном #" в источнике.

В разделе 6.10.3.2 стандарта C "Оператор #" он говорит:

Каждый # токен предварительной обработки в список заметок для функции макрос должен следовать параметр как следующий токен предварительной обработки в список заметок.

Проблема в том, что вы можете преобразовать макросы в строки, но вы не можете преобразовать случайные элементы, которые не являются аргументами макроса.

Итак, для достижения эффекта, которым вы пользуетесь, вам, безусловно, нужно сделать дополнительную работу.

#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);
}

Я не совсем понимаю, как вы планируете использовать макросы, и как вы планируете избегать повторения вообще. Этот более подробный пример может быть более информативным. Использование макроса, эквивалентного STR_VALUE, - это идиома, необходимая для получения желаемого результата.

#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);
}

* В то время, когда этот ответ был впервые написан, shoosh имя "Shy" было как часть имени.

Ответ 2

@Джонатан Леффлер: Спасибо. Ваше решение работает.

Полный рабочий пример:

/** 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;
}

Пример:

$ gcc -Wall -DTEST_FUN=another_func macro_sub.c -o macro_sub && ./macro_sub
do something else
TEST_FUN_NAME=another_func

Ответ 3

#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;
}

Ссылка: Wikipedia препроцессор C страница

Ответ 4

#define TEST_FUN_NAME #FUNC_NAME

см. здесь