【问题标题】:String literal to char array literal字符串文字到 char 数组文字
【发布时间】:2021-03-15 21:43:51
【问题描述】:

我正在编写一些涉及编写 char 数组的代码,如下所示:

char arr[] = { CONST1, CONST2, 'h', 'e', 'l', 'l', 'o' };

CONST1CONST2 是枚举值) 有什么方法可以将这个字符字符串表示为单个字符串文字(通过预处理器宏或其他方式)?例如

char arr = {CONST1, CONST2, "hello"};

用单引号和双引号括起来会产生预期的编译器错误。

【问题讨论】:

  • 假设 CONST1CONST2 定义类似于 'a',您可以将它们重新定义为 "a",然后只需 char arr[] = CONST1 CONST2 "hello";(请注意,它不完全等同于您的初始sn-p - 因为那个缺少空终止)
  • @EugeneSh。应该在问题中指定 - CONST1 等是来自枚举的值,即整数
  • 嗯,这会让事情变得更复杂
  • 这对我的代码来说不是必要的,它只会让编写它(因为这是在开发过程中经常改变的部分)少了一件苦差事,而且看起来很奇怪太费力了。

标签: c gcc c-preprocessor


【解决方案1】:

这是您的宏,请明智地使用它:

#define ENUM )(enum,
#define STR )(str,

#define MAKE_ARRAY(name, seq) \
    char name[END( MAKE_ARRAY_SIZEOF_LOOP_A(start, seq) )]; \
    char *MAKE_ARRAY_ptr = name; \
    END( MAKE_ARRAY_WRITE_LOOP_A(start, seq) ) \
    *MAKE_ARRAY_ptr = '\0';
    
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y

#define END(...) END_(__VA_ARGS__)
#define END_(...) __VA_ARGS__##_END

#define MAKE_ARRAY_ptr CAT(_MAKE_ARRAY_ptr_,__LINE__)

#define MAKE_ARRAY_SIZEOF_start(x) 1
#define MAKE_ARRAY_SIZEOF_enum(x) +1
#define MAKE_ARRAY_SIZEOF_str(x) +sizeof(x)-1
#define MAKE_ARRAY_SIZEOF_LOOP_BODY(x,y) CAT(MAKE_ARRAY_SIZEOF_,x)(y)
#define MAKE_ARRAY_SIZEOF_LOOP_A(...) MAKE_ARRAY_SIZEOF_LOOP_BODY(__VA_ARGS__) MAKE_ARRAY_SIZEOF_LOOP_B
#define MAKE_ARRAY_SIZEOF_LOOP_B(...) MAKE_ARRAY_SIZEOF_LOOP_BODY(__VA_ARGS__) MAKE_ARRAY_SIZEOF_LOOP_A
#define MAKE_ARRAY_SIZEOF_LOOP_A_END
#define MAKE_ARRAY_SIZEOF_LOOP_B_END

#define MAKE_ARRAY_WRITE_start(x)
#define MAKE_ARRAY_WRITE_enum(x) *MAKE_ARRAY_ptr++ = (char)x;
#define MAKE_ARRAY_WRITE_str(x) for (size_t i = 0; i < sizeof(x)-1; i++) *MAKE_ARRAY_ptr++ = x[i];
#define MAKE_ARRAY_WRITE_LOOP_BODY(x,y) CAT(MAKE_ARRAY_WRITE_,x)(y)
#define MAKE_ARRAY_WRITE_LOOP_A(...) MAKE_ARRAY_WRITE_LOOP_BODY(__VA_ARGS__) MAKE_ARRAY_WRITE_LOOP_B
#define MAKE_ARRAY_WRITE_LOOP_B(...) MAKE_ARRAY_WRITE_LOOP_BODY(__VA_ARGS__) MAKE_ARRAY_WRITE_LOOP_A
#define MAKE_ARRAY_WRITE_LOOP_A_END
#define MAKE_ARRAY_WRITE_LOOP_B_END

用法:

enum E {e1, e2};

int main()
{
    MAKE_ARRAY(foo, ENUM e1 ENUM e2 STR "abc")
}

这扩展为:

char foo[1 +1 +1 +sizeof("abc")-1];
char *_MAKE_ARRAY_ptr_42 = foo;
*_MAKE_ARRAY_ptr_42++ = (char)e1;
*_MAKE_ARRAY_ptr_42++ = (char)e2;
for (size_t i = 0; i < sizeof("abc")-1; i++)
    *_MAKE_ARRAY_ptr_42++ = "abc"[i];
*_MAKE_ARRAY_ptr_42 = '\0';

这里:

  • _MAKE_ARRAY_ptr_42 是一个辅助指针。末尾的数字来自__LINE__,所以不能在一行中使用两个MAKE_ARRAYs。如果需要,请将其替换为全局变量。
  • char foo[1 +1 +1 +sizeof("abc")-1];:
    • 开头的1 总是为空终止符腾出空间。
    • 两个+1s 来自ENUM &lt;name&gt;
    • +sizeof("abc")-1 来自STR "abc"
  • *_MAKE_ARRAY_ptr_42 = '\0'; 在末尾添加了一个空终止符。

【讨论】:

  • 哎哟。我希望你不打算真正使用它:) 我肯定会在代码审查中抨击它。
  • @EugeneSh。我在我的宠物项目中使用了更糟糕的。然而,在工作中尝试它。 :P
猜你喜欢
  • 1970-01-01
  • 2011-04-19
  • 2012-05-03
  • 1970-01-01
  • 2021-10-05
  • 1970-01-01
  • 2014-05-01
  • 2021-09-17
  • 1970-01-01
相关资源
最近更新 更多