我试着做一个像这样的宏:

#define STRING(i) \
struct STRING##i \
{ \
    size_t len; \
    char chars[i]; \
}

但问题是,它适用于constexpr个这样的论点:

constexpr int ten = 10;
STRING(ten) mystr;

我不想这样,因为STRING(ten)STRING(10)不是兼容的类型,这可能会让这个宏的用户感到困惑.

我试过以下方法:

#define STRING(i) \
struct STRING##i \
{ \
    _Static_assert( CAT(i, ul) , "must be nonzero literal"); \
    size_t len; \
    char chars[i]; \
}

它在文字上附加ul,使其成为无符号的长文字,但对非文字失败,因为它使其成为不同的标识符.但是这样做的问题是如果用户具有另一个名为tenulconstexpr.

我想知道是否有更好的方法来使这个宏失败,除非提供了一个整数文字.


编辑

为了补充公认的答案,我做了:

#define STRING(i) \
struct STRING##i \
{ \
    _Static_assert((1##i##1ul || i##8ul || 1), "argument must be positive decimal integer literal"); \
    size_t len; \
    char chars[i]; \
}

这确保了不接受八进制和十六进制,只接受十进制文字.

推荐答案

有效标识符以字母字符或下划线开头.有效的整数字面值以数字开头.如果有一种方法来判断#i(转换成字符串的宏参数)的第一个字符是否是数字at compile time就好了.但据我所知,使用(#i)[0]只在运行时起作用.

The question is tagged so here is the only method I could think of and only works in C23:

在6.6常量表达式中:

从 struct 或联合常数开始,成员访问.运算符可用于形成如上所述的命名常数或复合文字常数.

这意味着在理论上,你应该能够拥有如下代码:

#define IS_LITERAL(i)\
_Static_assert(((constexpr union {unsigned char f, s[sizeof(#i)];}){.s = #i}).f - '0' <= 9,\
    "Not numeric literal");

这样做是创建一个包含char字段和char[]字段的常量匿名联合,并使用.运算符来获取char字段,这将是char[]字段的第一个字符,然后判断该字符是否为数字.

Edit:上面的技术调用未定义的行为/不需要按照以下规则编译:

如果是成员访问操作员.访问联合常数的成员时,被访问的成员应与联合常数的初始化器初始化的成员相同.


或者,如果您希望一个非文字整数值的编译时错误,并且不介意失go 使用十六进制常数的能力,您可以使用用途:

#define IS_LITERAL(i) _Static_assert(1##i || 1); // Or int dummy = 1##i; or similar

如果i是一个标识符,那么i前面加1就不是一个有效的标识符名称,但是在八进制或十进制常数前面加1仍然是一个有效的表达式.

Note: 1##i##0也可以用于阻止标识符,例如lul.

C++相关问答推荐

是否可以在C中进行D3 D12申请?

由Go调用E.C.引起的内存快速增长

正在try 将文件/文件夹名从目录 struct 存储到链接列表

ESP32在vTaskDelay上崩溃

使用双指针动态分配和初始化2D数组

为什么我的Hello World EFI程序构建不正确?

在C中包装两个数组?

如何使用唯一数字对整型进行分区

我在反转双向链表时遇到问题

C:如何将此代码转换为与数组一起使用?

C语言中奇怪的输出打印数组

GETS()在C++中重复它前面的行

c程序,让用户输入两类数字,并给出输出用户输入多少个数字

STM32 FATFS用户手册(Um1721)中的代码正确吗?

传递给函数的 struct 中的数组

C程序printf在getchar while循环后不工作

尽管将其标记为易失性,但 gcc 是否优化了我的等待代码?

与 C 相比,C++ 中无副作用的无限循环的好处是 UB?

我该如何处理这个 C 90 代码中的内存泄漏?

初始化动态分配的布尔二维数组的最佳方法是什么?