【问题标题】:How to concatenate a variable string with literal string in C macro?如何在 C 宏中将变量字符串与文字字符串连接起来?
【发布时间】:2019-12-15 19:43:36
【问题描述】:

我正在创建一个接受 2 个字符串的宏:变量字符串和文字字符串。如何将它们组合成一个接受单个变量的函数?

我知道我们可以在一个宏中组合两个文字字符串。

#define LOGPRINT(x,y) func(x y)
#define LOGPRINTSINGLE(x) func(x)

func(char *fmt)
{
   printf(fmt);
}

下面的代码可以正常工作:

char * test = "hey "; 

LOGPRINT("hello ", "world!");
LOGPRINTSINGLE(hey);

但是下面的代码失败了。

LOGPRINT(test, "world!");

如何在宏中将变量字符串 test 与文字字符串“world”结合起来? 预期结果是“嘿世界”被传递给 func()。

**编辑/注意:规则是我只允许更改这一侧的代码,而不是调用者和 func()。

【问题讨论】:

  • 简短的(实际上是唯一的)答案是:你不能。预处理器是在“正确”编译之前作为单独步骤运行的。因此,预处理器对变量一无所知,甚至对变量的可能内容一无所知,因为这仅在运行时才知道,可能在编译后很长时间。
  • 如果你真的使用 C++(如标签建议的那样),那么你可以这样做#define LOGPRINT(x,y) func((std::string(x) + std::string(y)).c_str())
  • 请选择一种编程语言。
  • 使用“真实”函数而不是宏。它接受两个const char * 参数;你的问题都消失了。甚至是代码膨胀问题。
  • XY 问题。您不需要字符串连接。您需要一个有效的日志宏。具体来说,就像 printf 一样工作。

标签: c++ c macros gnu preprocessor


【解决方案1】:

如果包含“字符串”STL,使用 c++ 字符串非常简单

更改#define LOGPRINT(x,y) func(x y)

#define LOGPRINT(x,y) func((std::string(x) + std::string(y)).data())

#define LOGPRINT(x,y) func(std::string(x).append(y).data())

【讨论】:

    【解决方案2】:

    也许不是世界上最漂亮或最安全的宏,但它确实有效 :-)

    #include <stdio.h>
    #include <string.h>
    
    #define LOGPRINT(x,y)                       \
    {                                           \
    char dest[strlen(x) + strlen(y) + 1];       \
    memcpy(dest, x, strlen(x));                 \
    memcpy(dest + strlen(x), y, strlen(y));     \
    dest[strlen(x) + strlen(y)] = 0;            \
    func(dest);                                 \
    }
    #define LOGPRINTSINGLE(x) func(x)
    
    void func(char *fmt)
    {
       printf(fmt);
    }
    
    
    int main()
    {
        char * test = "hey "; 
    
        LOGPRINT("hello ", "world!");
        printf("\n");
        LOGPRINTSINGLE(test);
        printf("\n");
        LOGPRINT(test, "world!");
    
        return 0;
    }
    

    输出:

    hello world!
    hey
    hey world!
    

    【讨论】:

    • 计算机科学中只有两个难题:命名、缓存失效和一个错误。
    • 为了弄清楚 Antti Haapala 可能想说什么:dest 的大小减一。 ;
    • rofl,甚至没有在输出中注意到它 xD 这段美丽、可爱和奇妙的代码很好!
    • 您不需要使用strncpy - 因为您知道长度只需使用memcpy,它不会扫描终止的0。
    • 是的,我也注意到了这一点,但我并不关心它,因为它会导致相同的行为,因为使用 strncpy 而不是 strcpy。我不知道strncpy 的内部结构,在大多数架构上它可能比memcpy 慢一点。我会把它改成memcpy 看样子:-)
    猜你喜欢
    • 2017-04-17
    • 2023-01-24
    • 2013-10-20
    • 2011-05-13
    • 2020-07-31
    • 1970-01-01
    • 2020-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多