【问题标题】:Concatenate strings in #define without strcat在 #define 中连接字符串而不使用 strcat
【发布时间】:2018-06-19 17:33:14
【问题描述】:

在我正在处理的项目中,我有一个类似于此的代码:

#include<stdio.h>

struct parameter_struct{
    char *parameter_name;
    int parameter_value;
};

int main(){
  struct parameter_struct param1= {"x_custom_param1", 6};
  printf("parameter name: %s\n", param1.parameter_name);
  return 0;
}

我现在需要实现的是使用预定义的宏使参数名称动态化:

#define macro_custom "x_custom1_"  

所以参数名称应该是与“param1”子字符串连接的宏值。我的意思是它将是“x_custom1_param1”而不是实际的静态值“x_custom_param1”。

在我的项目中,所有参数都是这样静态声明的:

{"x_custom_param1", 6};

而且我不能碰这种代码结构。所以我不能在c函数中动态初始化这些参数,例如在这个函数中使用strcat。

所以我想到的是使用另一个#define with ## 语句。所以我的代码会是这样的:

#include<stdio.h>

#define macro_custom "x_custom1_"
#define f(g,h) g##h


struct parameter_struct{
    char *parameter_name;
    int parameter_value;
};

int main(){
  struct parameter_struct param1= {f(macro_custom, "param1"), 6};
  printf("parameter name : %s\n", param1.parameter_name);
  return 0;
}

但我得到一个编译错误:

error: pasting "macro_custom" and ""param1"" does not give a valid preprocessing token
   struct parameter_struct param1= {f(macro_custom, "param1"), 6};

这似乎是合乎逻辑的,因为我定义的宏没有返回带有##的字符串

有人知道如何纠正我的想法吗?还是有更好的主意?

【问题讨论】:

    标签: c concatenation c-preprocessor preprocessor-directive


    【解决方案1】:

    您正在寻找的功能是字符串粘贴。相邻的字符串常量会被编译器组合起来——你不需要操作符。

    #define f(g, h) (g h)
    

    请记住,此技巧仅适用于字符串常量。它不适用于变量。

    【讨论】:

      【解决方案2】:

      这比我想象的要简单。我在一个旧项目中找到它。

      #include<stdio.h>
      
      #define macro_custom "x_custom1_"
      
      struct parameter_struct{
          char *parameter_name;
          int parameter_value;
      };
      
      int main(){
        struct parameter_struct param1= {macro_custom"param1", 6};
        printf("parameter name : %s\n", param1.parameter_name);
        return 0;
      }
      

      【讨论】:

        【解决方案3】:

        字符串文字可以通过这种方式连接"str1""str2"

        宏函数可以连接两个字符串文字 - #define STRCAT(str1, str2) str1##str2

        当涉及到变量时,你使用strcat()

        更有效的方法是使用字符串管理实用程序,例如 GString。 它跟踪字符串的结尾并为您处理内存扩展。 跟踪字符串的结尾始终是免费的操作,因为无论如何复制它时总是会到达结尾。

        另一种方法是使用strchr() 找到\0,然后在这个偏移量加上一个字节前向复制字符串。


        另外,我认为 OP 的问题会更清楚,如果它指出编译/预处理器中的字符串连接(下面的评论对它发生的确切阶段有所了解)需要时间。 这些概念揭示了整个不同的宇宙。

        【讨论】:

        • 这是不正确的。字符串文字连接发生在翻译阶段 6 中,您需要的只是两个连续的字符串文字标记。预处理器是翻译阶段 4;在两个字符串文字上严格使用## 是无效的(即使它在某些特定实现上“有效”),因为您不能将两个字符串文字组合成一个有效的令牌。
        • @HWalters 我没有详细说明,我只是想指出在运行时发生的strcat 与早期短语中的字符串连接非常不同。不过,您在这方面的信息似乎比我领先得多。
        • 您的 STRCAT 很有用,只是不适用于字符串文字连接。我提到这一点的唯一原因是我看到人们对此感到困惑(即,在为 _Pragma 构建参数时,这种区别非常重要)。
        【解决方案4】:

        尝试使用“#”预处理运算符将宏参数转换为字符串常量。

        #define NEW_PARA_STRUCT(paramx, value) struct parameter_struct paramx={(macro_custom #paramx), value}
        

        例子:

        #include <stdio.h>
        
        #define macro_custom "x_custom1_"
        #define f(g,h) (g h)
        
        #define NEW_PARA_STRUCT(paramx, value) struct parameter_struct paramx={(macro_custom #paramx), value}
        
        struct parameter_struct{
            char *parameter_name;
            int parameter_value;
        };
        
        int main(){
          struct parameter_struct param1= {f(macro_custom, "param1"), 6};
          NEW_PARA_STRUCT(param2, 7);
        
          printf("parameter name : %s\n", param1.parameter_name);
          printf("parameter name : %s\n", param2.parameter_name);
          return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-08-19
          • 2013-07-07
          • 1970-01-01
          • 1970-01-01
          • 2017-08-27
          • 1970-01-01
          • 2011-06-17
          相关资源
          最近更新 更多