【问题标题】:Editing/Redefining a Constant String: Yes I'm aware of the contradiction编辑/重新定义常量字符串:是的,我知道矛盾
【发布时间】:2013-02-11 04:44:50
【问题描述】:

我正在尝试更改常量变量的值,是的,我知道我正在做的事情的矛盾,但是我的疯狂有一种方法。

你看我正在用一种非常类似于 C/C++ 的语言编写,称为 4dm,但它不允许函数之外的任何代码,所以我试图通过使用预处理器命令来克服这个问题.原因是我可以在语言中实现某种形式的专业化。第一步涉及能够编辑常量字符串。

尽管这是一种不同的语言,但预处理器的运行方式与 C 和 C++ 编译器完全相同:

#define MY_STR "abc"
#define CONCAT(s) \
    #define TEMP MY_STR \  // store MY_STR in TEMP_STR
    #undef MY_STR \        // undefine MY_STR
    #define MY_STR TEMP s  // redefine MY_STR so it contains the old value plus the new one

CONCAT(def)
printf("%s\n", MY_STR);  // should hopefully print out "abc def"

以下是连接字符串的简单尝试,但我收到一个编译错误,提示 MY_STR is not defined 任何想法如何解决这个问题?

#define MY_STR abc
#define TEMP MY_STR
#undef MY_STR
#define MY_STR TEMP def

void test()
{
    print(MY_STR);
}

【问题讨论】:

  • 修改常量字符串会导致 C++ 中的未定义行为,但您在这里所做的是重新定义预处理器宏,而不是修改 const string。这是完全不同的两件事。你还有什么问题?
  • 你正走向失望!提供有关您要达到的目标的更多信息。可能还有其他方法可以实现。
  • @paddy 我会解释它,但它会占用大量文本并将问题从连接/重新定义常量到递归和规范的切线中解开,所以我会提出一个新问题
  • 顺便说一句,C 预处理器不是这样工作的,而且从来没有。您不能将指令放在宏中。
  • @JakeM 您正面临 XY 问题。你有问题 X,你认为你可以用 Y 解决它,所以你问 Y。但 Y 可能不是解决方案。我们需要对您真正想要实现的目标进行高级描述,因此我们可以告诉您预处理器是否可以做到这一点。 (如果您确实拥有符合 C 或 C++ 标准的预处理器。)

标签: c-preprocessor preprocessor-directive


【解决方案1】:

在您的第一个示例中,您尝试将宏扩展为 #define 预处理器命令。你不能那样做;预处理器产生C 代码(或其他),在宏扩展中看起来像预处理器指令的各种东西实际上不是预处理器指令。这会产生错误,因为宏定义中的# 是“stringify”运算符,它后面必须跟一个宏参数。 (另外,\ 必须在行尾。你不能在后面加上评论。)

在你的第二个例子中,当你写:

#define TEMP MY_STR

这正是它的作用:它将宏 TEMP 定义为具有值 MY_STR(不是 MY_STR 的宏扩展,只是六个字符的标记 MY_STR

之后,你

#define MY_STR TEMP def

这将宏 MY_STR 定义为两个标记 TEMPdef

然后你展开MY_STR

print(MY_STR);

这会导致它被TEMP def 替换。扩展再次通过宏处理器运行,这导致TEMPMY_STR 替换。这再次通过宏处理器运行,但这次MY_STR 没有展开,因为您无法在宏的展开中展开宏。所以这次它保持为MY_STR,你最终得到:

print(MY_STR def);

MY_STR 未定义(宏不是定义),因此编译器抱怨 MY_STR 未定义。

【讨论】:

    【解决方案2】:

    一个好的编译器会将一个字符串常量放在一个块中,该块将被标记为写保护,任何修改它的尝试都会导致某种操作系统异常。

    这不是你在这里所做的——你是根据旧字符串定义一个新字符串。这适用于 C 和 C++,并且可能也适用于您的语言。

    由于您是在定义自己的语言,您会比我们更清楚它会如何反应!

    【讨论】:

    • 请看编辑,它显示了编译器的反应,说 MY_STR 没有定义。不确定如何解决该错误?
    • @JakeM 那时的问题是您将MY_STR 定义为abc,而它应该是"abc"(注意双引号)。
    • @jogojapan 谢谢我已经添加了引号。但是编译错误仍然出现在函数测试中说MY STR not defined
    【解决方案3】:

    关于您尝试使用CONCAT 实现的目标,C99 标准的第 6.10.3.4 ¶3 节说(部分引用):

    生成的完全被宏替换的预处理标记序列即使类似于一个预处理指令,也不会被处理为预处理指令

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-03
      • 2013-02-02
      • 2022-10-24
      • 1970-01-01
      • 2017-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多