C:断言表达式是字符串文字

Kev*_*ier 4 c gcc static-assert string-literals

我想要一个静态断言来确保给定的表达式是字符串文字。我试过这个:

#define SAME_TYPES(x, y)                    __builtin_types_compatible_p(typeof(x), typeof(y))
#define IS_ARRAY(x)                         !SAME_TYPES((x), &(x)[0])
#define IS_COMPILE_TIME_STR(x)              IS_ARRAY(x) && #x[0] == '"'
#define ASSERT_COMPILE_TIME_STR(x)          static_assert(IS_COMPILE_TIME_STR(x), "Only static allocated compile time strings are allowed, but got this: " #x)

/*
 * ASSERT_COMPILE_TIME_STR("hey"); <-- this is fine
 * ASSERT_COMPILE_TIME_STR(1234);  <-- this should fail
 */
Run Code Online (Sandbox Code Playgroud)

不幸的是,ASSERT_COMPILE_TIME_STR不起作用,因为#x[0] == '"'似乎不是编译时常量。

还有其他方法可以实现这一目标吗?它只需要使用 gcc 进行编译,所以任何类型的扩展都可以:)

多谢

dbu*_*ush 7

C 允许连续的字符串常量,编译器将其组合成单个常量。您可以通过尝试将字符串常量与相关表达式对齐来利用此问题。

#define IS_STR_CONT(x) (void)((void)(x),&(""x""))
Run Code Online (Sandbox Code Playgroud)

关于上述内容的一些注意事项:

  • 逗号运算符(x)左侧的 有助于捕获某些类型的非表达式,例如0+
  • 获取地址可确保结果是左值
  • void逗号运算符左侧和完整表达式的强制转换可防止出现有关无效表达式的警告。

上面接受了这一点,没有警告或错误:

IS_STR_CONT("hello");
Run Code Online (Sandbox Code Playgroud)

当产生一个或多个错误时:

IS_STR_CONT(123);
IS_STR_CONT(0+);
IS_STR_CONT(+0);
int i=0;
IS_STR_CONT((i++,"xxx"));
IS_STR_CONT(!"abc");
IS_STR_CONT(4 + "abc");
IS_STR_CONT(*"abc");
IS_STR_CONT("ad" == "abc");
Run Code Online (Sandbox Code Playgroud)

这并不完美,但应该可以捕获大多数情况。