在C语言中运行时修改宏定义

33

我定义了一个宏,但我需要根据条件在运行时更改该值。如何实现这一点?


2
宏通过预处理器进行处理。它们在运行时无法被修改。这是一个宏常量还是带参数的函数宏? - user195488
7
顺便说一下,这是一个很好的问题,所以我们可以在Stackoverflow上回答“不”。 - Prof. Falken
2
您能否提供您宏的示例——在我看来,您似乎并不需要运行时可更新的宏,这没有任何意义——而是需要具有一个或多个附加参数的宏。或者也许您可以重新设计您的代码。 - rudolf_franek
1
#定义SIZE 100 如果在代码中想要使用它,有时应该是50。那么我的步骤是什么?因为我想根据SIZE制作菜单列表。 如果(某些情况)则创建50个菜单 否则创建SIZE个菜单 目前我所做的就是创建一个变量,并根据条件更改变量的值,而这个变量之前是由宏更新的。 - lighthouse
2
@lighthouse,变量是正确的选择。 - Prof. Falken
显示剩余11条评论
5个回答

35

宏在源文件编译之前被预处理器替换为其值。你无法在运行时更改宏的值。

如果您可以更详细地解释您想要实现的目标,那么无疑会有其他不需要使用宏的解决方案来解决您的问题。


如果将宏分配给具有获取所需值并返回的逻辑的函数,那么宏是否能够返回动态值呢? - Harsh S.
如果宏解析为函数,则预处理器将在编译C++文件之前用函数名称替换宏。在这种情况下,宏本身并不变得“动态”。相反,宏解析的东西是返回运行时值的东西。 - fbrereto

30

您无法更改宏本身,即它所展开的内容,但是您可能可以更改其中包含宏的表达式的值。以下是一个非常愚蠢的例子:

#include <stdio.h>

#define UNCHANGEABLE_VALUE 5
#define CHANGEABLE_VALUE foo

int foo = 5;

int main() {
    printf("%d %d\n", UNCHANGEABLE_VALUE, CHANGEABLE_VALUE);
    CHANGEABLE_VALUE = 10;
    printf("%d %d\n", UNCHANGEABLE_VALUE, CHANGEABLE_VALUE);
}
因此,你的问题的答案取决于你希望改变宏对代码产生何种影响。
当然,5 是一个编译时常量,而 foo 不是,因此如果你打算将 CHANGEABLE_VALUE 用作 case 标签或其他用途,则这样做是行不通的。
请记住,在 C 源代码的翻译过程中有两个(实际上更多)阶段。在第一个阶段(我们关心的两个阶段之一)中,宏会被展开。一旦所有这些都完成了,程序就会被“语法和语义分析”,正如 5.1.1.2/2 所说。这两个步骤通常被称为“预处理”和“编译”(虽然具有歧义,整个翻译过程也经常被称为“编译”)。它们甚至可以由不同的程序实现,其中“编译器”按需运行“预处理器”,然后再执行其他操作。因此,在运行时尝试返回并更改宏展开的内容,时间已经过晚了。

1
嗯..这个答案说你可以将宏用作case标签:https://dev59.com/onI-5IYBdhLWcg3wxruQ#1674118 - user195488
5
“你不能将const int对象用作case标签(而宏会起作用)”。这并不意味着任何宏都是合法的case标签,或者使用宏会在case标签中神奇地让你可以使用其他不能使用的东西。AndreyT将 const int对象与整数文字定义的宏进行比较。 case UNCHANGEABLE_VALUE: 是可以的,case CHANGEABLE_VALUE: 不行。 - Steve Jessop

13
你做不到。宏是由预处理器扩展的,甚至在代码编译之前就发生了。这只是纯文本替换。
如果您需要在运行时更改某些内容,请将宏替换为实际的函数调用。

请您能否提供一个简单的例子,说明如何使用函数调用来替换它? - utvecklare

7
您无法这样做。
由于宏在编译之前由预处理器解析,因此其内容直接复制到使用它的地方。
您仍然可以使用参数来插入一个条件语句,具体取决于您想要什么,或者使用一个可调用范围内可访问的变量。
如果您想更改单个值,则最好使用全局范围变量,即使此类行为不被推荐。(因为宏的密集使用)

4

根据您的需求,有多种方式可以实现。

使用全局变量代替宏

// someincludefile.h
extern static int foo;

// someincludefile.c
static int foo = 5;

// someotherfile.c
#include "someincludefile.h"
printf("%d\n", foo); // >> 5
foo = -5;
printf("%d\n", foo); // >> -5

您可以切换的条件

// someincludefile.h
extern static int condition;
#define FOO1 (5)
#define FOO2 (-5)
#define FOO (condition ? (FOO1) : (FOO2))

// someincludefile.c
static int condition = 1;

// someotherfile.c
#include "someincludefile.h"
printf("%d\n", FOO); // >> 5
condition = 0;
printf("%d\n", FOO); // >> -5

本地和动态评估的条件

// someincludefile.h
#define CONDITION (bar >= 0)
#define FOO1 (5)
#define FOO2 (-5)
#define FOO ((CONDITION) ? (FOO1) : (FOO2))

// someotherfile.c
#include "someincludefile.h"
int bar = 1;
printf("%d\n", FOO); // >> 5
bar = -1;
printf("%d\n", FOO); // >> -5

在最后一个示例中,条件的评估将被视为在您的本地作用域中编写其代码,因此您可以在其中使用本地变量和/或参数,但如果需要,您也可以使用全局变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接