2008-10-12 18 views
43

Örneğin, 'func_name' kelimesini iki kez yazmaktan nasıl kaçınmanız gerekir?C makrosu değerinden nasıl char dizesi yapılır?

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

Ben Single Point of Truth kuralı takip etmek istiyorum. C önişlemci

Versiyon:

$ cpp --version 
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14) 
+0

([dizeleri oluşturmak için C Makro] olası çift http://stackoverflow.com/questions/798221/c-macros -to-oluşturmak-dizeleri) – rjstelling

cevap

67

He who is Shy* size bir answer mikrop verdi, ama sadece mikrop. C ısıtma-öncesi işlemci bir dizeye bir değer dönüştürmek için temel teknik '#' operatör ile gerçekten de, önerilen çözümün bir basit çevirisi bir derleme hata alır:

#define TEST_FUNC test_func 
#define TEST_FUNC_NAME #TEST_FUNC 

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

yazım hatası verildi 'koyar()' satırı - sorun kaynağında bir 'başıboş' '. C standardının bölümünde 6.10.3.2 yılında

, '# operatörü', diyor:

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.

sorun dizeleri makro argümanlar dönüştürebilirsiniz olmasıdır - ama rastgele dönüştürmek olamaz Makro bağımsız değişkenler olmayan öğeler.

Böylece, peşinden olduğunuz etkiyi elde etmek için, kesinlikle fazladan iş yapmak zorundasınız.

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

Sana makroları kullanmayı planlıyorsanız nasıl tamamen net değilim, ve nasıl tamamen tekrarını önlemek planlıyoruz. Bu biraz daha ayrıntılı örnek, daha bilgilendirici olabilir. STR_VALUE değerine eşdeğer bir makronun kullanılması, istenen sonucu elde etmek için gerekli olan bir deyimdir. Bu cevap ilk yazıldığı anda


*

#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 adının bir parçası olarak 'Shy 'ın adı kullanılıyor'.

+0

Çalışıyor.Teşekkür ederim. Code için motivasyon yansıtan bir çalışma örneği yayınladık. Bir yorumun http://stackoverflow.com/questions/195975/how-to-make-a-char-string-from-ac-macros-value#196093 – jfs

+0

Neredeyse kelimesi kelimesine yeniden yazma aslen 2012-10-12 21:37 yapımı (bunun yerine __func__' 'kalın bir __func__ gösterdi) - tabii ki, C99, fonksiyon adı ortalama işlev olarak' __func__' önceden tanımlanmış bir tanımlayıcı kullanabilir. Ancak, bu işlevin dışında bir yardım değildir ve işlev adı dizesinin gerçekten gerekli olduğu yer burasıdır. –

+0

ikinci kodunuz benim için çalışmıyor. Ben 'test_func' sanırım OP durumu için bir makro olmalıdır. #define test_func my_test_func dosyasını koyarsanız. (böylece test_func'i bir makro haline getirerek), hala test_func '' my_test_func' 'yazmıyor. –

-2

#define TEST_FUN_NAME #FUNC_NAME

here

+2

çalışmıyor. Cevabımı gör. – jfs

+2

Bu gerçekten yanlış - ayrıca yanıtıma da bakın. Ayrıca 4 oy oyu olması şaşırtıcı. Sorun şu ki, dikkatlice düşünmüyorsanız, az ya da çok doğru olabilir. –

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

Referans bkz: Wikipedia'nın C preprocessor sayfa

+1

Ya işe yaramıyor. Cevabımı gör. – jfs

12

@Jonathan Leffler: Teşekkürler. Çözümünüz çalışıyor.

tam bir çalışma örneği:

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

Örnek:

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