如何使用C/C++预处理器连接字符串文字和字节值[关闭]

zbdgwd5y  于 2023-05-08  发布在  C/C++
关注(0)|答案(1)|浏览(127)

已关闭,此问题需要details or clarity。目前不接受答复。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。

昨天关门了。
Improve this question
我正在为一个微控制器编写一些代码,我试图通过将一系列带有字符串、char和byte参数的函数调用转换成编译时常量字符串,然后将其解释为控制代码,从而节省相当多的程序内存。所使用的值在编译时都是已知的,所以我不期望在这里有任何魔力。问题是我找不到任何方法来连接一个字符串与字节值,例如。如果我有一个控制字符“W”和一个值“32”,我想创建一个3字节的char *,其中包含“W\x20\x0”在字符串中嵌入NULL值并不是解析它的方式的问题。
我在这个主题上发现的大多数问题都提供了连接字节的字符串化值的解决方案,这在理论上是可行的,但它使解析控制序列变得更加复杂,因为现在一个字节可以多达3个字符,这也占用了字符串中更多的空间,这与练习的目的背道而驰。
到目前为止,我已经尝试过:

  • 将所有内容视为字符以创建逗号分隔的char数组。对于char值和字节来说效果很好(显然),但是似乎没有办法使用宏将字符串文本添加到char[]中,手动将所有字符串文本转换为char数组对于可读性并不好
  • 将所有内容视为字符串,这样可以保持字符串和字符的可读性,但现在字节值就成问题了。我找不到办法让预处理器把32变成“\x20”(甚至“\x32”)。我发现的最好的解决方法是将所有字节值转换为字符串作为宏的输入,但是DO_SOME_COMMAND(“\x20”)比DO_SOME_COMMAND(32)要差一些。(目前为止,这似乎是最好的选择)
  • 忘记宏,使用memcpy或printf连接字符数组和字符串,依靠编译器将其优化为编译时常量。这似乎对简单的情况下工作,但我不确定在编译器窒息之前我能有多疯狂。我也发现了这个方法的很多缺点,即它需要嵌套宏,而不是一个接一个地链接它们和/或创建一堆变体来处理char * 和byte值的不同混合。此外,这使得它不可能直接编译到程序内存中,即使编译器能够将其简化为一个简单的字符串赋值,这在一定程度上限制了我的选择。
  • 当然,总是在外部处理输入,然后将它们作为单个字符串文字粘贴回源代码,但这几乎看起来像作弊,并且不可能维护。我希望把它作为一个宏,这样别人就可以看到它,例如。SET_CURSOR(20,40)而不是“C\x14\x28”

也许我对预处理器的要求太多了,但感觉应该有某种可行的方法来实现这一点。所以,这可能吗,还是我要求太多了?

vmdwslir

vmdwslir1#

SET_CURSOR(20,40)而不是“C\x14\x28”
在C* 中,一个简单的方法是只做一个复合字面量:

#define SET_CURSOR(a, b)  (const char[]){'C', a, b}

在C中,上面的代码是无效的,这说明了语言之间的差异。在C中,你可以示例化一个模板:

template<int x, int y>
struct SetCursorDetail {
    constexpr static const char value[3] = {'C', x, y};
};
#define SET_CURSOR(x, y)  SetCursorDetail<x, y>::value
const char *str = SET_CURSOR(20, 40);

我们可以通过使用所有可能值的字典将数字替换为字符串文字来进行“真实的”替换以获得字符串文字。然后,连续的字符串文字由编译器连接。所以我们可以这样做:

/* dictionary integer to character */
#define ITOC_0  "\x0"
#define ITOC_1  "\x1"
#define ITOC_2  "\x2"
#define ITOC_3  "\x3"
/* etc */
#define ITOC_20  "\x14"
/* etc */
#define ITOC_40  "\x28"
/* etc */
#define ITOC(x)  ITOC_##x

#define SET_CURSOR(a, b)  "C" ITOC(a) ITOC(b)

const char *str = SET_CURSOR(20, 40);  // "C" "\x14" "\x28";

相关问题