我想创建一个C宏,它创建一个名称基于行号的函数.我以为我可以做类似的事情(真正的函数会在括号内有声明):
#define UNIQUE static void Unique_##__LINE__(void) {}
Run Code Online (Sandbox Code Playgroud)
我希望将扩展到以下内容:
static void Unique_23(void) {}
Run Code Online (Sandbox Code Playgroud)
这不起作用.使用令牌连接,定位宏按字面处理,最终扩展为:
static void Unique___LINE__(void) {}
Run Code Online (Sandbox Code Playgroud)
这可能吗?
(是的,无论这看起来多么无用,我都有一个真正的理由要这样做).
正如我之前的许多问题所述,我正在通过K&R工作,目前正在进入预处理器.其中一个更有意思的事情 - 我之前从未尝试过的任何学习C的尝试 - 是##预处理器操作员.根据K&R的说法:
预处理器运算符
##提供了一种在宏扩展期间连接实际参数的方法.如果替换文本中##的参数与a相邻,则参数将替换为实际参数,##并删除周围的空白区域,并重新扫描结果.例如,宏paste连接其两个参数:
#define paste(front, back) front ## back所以
paste(name, 1)创建令牌name1.
如何以及为什么有人会在现实世界中使用它?它的使用的实际例子是什么,有什么需要考虑的?
我对预处理器如何工作的心理模型显然是不完整的,这让我发疯.
我想连接两个标记,但第二个标记应该首先扩展.
#define ANSWER 42
#define FOO foo_ ## ANSWER
Run Code Online (Sandbox Code Playgroud)
在这里,FOO扩展到foo_ANSWER,但我希望它foo_42.所以我定义了一个MERGE宏,希望在连接之前以某种方式扩展参数:
#define MERGE(x, y) x ## y
#define BAR MERGE(bar_, ANSWER)
Run Code Online (Sandbox Code Playgroud)
但BAR仍然扩大到bar_ANSWER而不是bar_42.所以我定义了另一个宏HELPER:
#define HELPER(x, y) MERGE(x, y)
#define BAZ HELPER(baz_, ANSWER)
Run Code Online (Sandbox Code Playgroud)
现在BAZ已成功扩展到baz_42.目前,这对我来说似乎很神奇.
任何人都可以向我解释这种行为吗?扩展规则如何正常工作?
在下面的代码中,该##怎么办?
#define MAKE_TYPE(myname) \
typedef int myname ## Id; \
Run Code Online (Sandbox Code Playgroud) 我想在它与其他东西连接之前评估一个令牌."问题"是标准将行为指定为
在重新检查替换列表以更换更多宏名称之前,删除替换列表中的##预处理标记的每个实例(不是来自参数),并将前面的预处理标记与以下预处理标记连接起来.
因此在下面的例子中,
#include <stdlib.h>
struct xy {
int x;
int y;
};
struct something {
char * s;
void *ptr;
int size;
struct xy *xys;
};
#define ARRAY_SIZE(a) ( sizeof(a) / sizeof((a)[0]) )
#define DECLARE_XY_BEGIN(prefix) \
struct xy prefix ## _xy_table[] = {
#define XY(x, y) {x, y},
#define DECLARE_XY_END(prefix) \
{0, 0} \
}; \
struct something prefix ## _something = { \
"", NULL, \
ARRAY_SIZE(prefix ## _xy_table), \
&(prefix ## _xy_table)[0], \
};
DECLARE_XY_BEGIN(linear1)
XY(0, 0) …Run Code Online (Sandbox Code Playgroud) 请解释一下代码
#include <stdio.h>
#define A(a,b) a##b
#define B(a) #a
#define C(a) B(a)
main()
{
printf("%s\n",C(A(1,2)));
printf("%s\n",B(A(1,2)));
}
Run Code Online (Sandbox Code Playgroud)
产量
12
A(1,2)
我不明白,第一个printf如何评估为12?是不是与第二个类似,因为C宏只是B宏的包装?
我试图弄清楚如何使用GCC为#include语句构建变量字符串.
我的想法是,对于我编写的每个源模块,我希望包含一个动态生成的C源头,它是在构建过程的早期创建的.
生成此文件不是问题.不幸的是,包括它在内.
到目前为止我所拥有的是(identities.h):
// identities.h
# define PASTER2(str) #str
# define PASTER(str) PASTER2(str ## .iden)
# define EVALUATOR(x) PASTER(x)
# define IDENTITIES_FILE EVALUATOR(__FILE__)
# include IDENTITIES_FILE
Run Code Online (Sandbox Code Playgroud)
理想情况下,这将被使用(main.c):
//main.c
# include "identities.h"
int main() {return 0;}
Run Code Online (Sandbox Code Playgroud)
在编译之前,预处理器将在一次传递中扩展为:
//main.c (preprocessed)
# include "main.c.iden"
int main() {return 0;}
Run Code Online (Sandbox Code Playgroud)
我正在使用的两个间接级别(PASTER和EVALUATOR)是这篇文章的结果.
不幸的是,这不起作用,我留下了错误:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
Run Code Online (Sandbox Code Playgroud)
我认为问题是include语句缺少引号..任何想法?
为什么代码:
#define EXPONENT(num, exp) num ## e ## exp
EXPONENT(1,1)
EXPONENT(1,-1)
EXPONENT(1,+1)
Run Code Online (Sandbox Code Playgroud)
预处理后的更改为:
1e1
1e- 1
1e+ 1
Run Code Online (Sandbox Code Playgroud)
而不是
1e1
1e-1
1e+1
Run Code Online (Sandbox Code Playgroud)
?我怀疑它可能是因为-1,+ 1被解析为两个标记(?).但是,在这种情况下如何获得后者的结果呢?
我试图找出一个问题,因为variadic宏的使用不正常.这是假设宏:
#define va(c, d, ...) c(d, __VA_ARGS__)
#define var(a, b, ...) va(__VA_ARGS__, a, b)
var(2, 3, printf, “%d %d %d\n”, 1);Run Code Online (Sandbox Code Playgroud)
对于gcc,预处理器将输出
printf("%d %d %d\n", 1, 2, 3)Run Code Online (Sandbox Code Playgroud)
但对于VS 2008,输出是
printf, “%d %d %d\n”, 1(2, 3);Run Code Online (Sandbox Code Playgroud)
我怀疑差异是由于对VA_ARGS的不同处理造成的,对于gcc,它首先将表达式扩展为va(printf,"%d%d%d \n",1,2,3),并处理1,2 ,3作为宏va 的VA_ARGS.但对于VS 2008,它将首先将b视为VA_ARGS用于宏va,然后进行扩展.
哪一个是C99可变参数宏的正确解释?或者我的用法属于未定义的行为?
我有一个普通的宏:
#define mSwitch( Root, Case ) Root##_Case_##Case
#define mSpecialDisplay( what, Val ) mSwitch(mSpecialDisplay,what)(Val)
#define mSpecialDisplay_Case_Int(Val) ...do stuff
#define mSpecialDisplay_Case_Float(Val) ...do stuff
...more special cases
Run Code Online (Sandbox Code Playgroud)
如何保证变量Case在粘贴之前完全展开mSwitch?
如果mSwitch传递一个文字值,它工作正常,但如果有多个间接层或中间操作,mSwitch最终会在完全展开之前粘贴其中一个.
我正在使用MSVC 2005.
有没有一种简单的方法可以确保参数在粘贴完成之前完全展开?
谢谢
好吧,举一个例子可能并不难:
#define mMDebugInfo( ... ) mMDebugExp( mMDebugInfo_( 0, __VA_ARGS__ ) )
#define mMDebugInfo_( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (C, __VA_ARGS__) )
#define mMDebugInfoRep( C, ... ) mMXP##C( mMDebugInfo_ )mMXP##C((mMIInc(C),__VA_ARGS__)) //(mMExpDo(mMGlue( mM, C)##DebugInfo_(mMIInc(C),__VA_ARGS__))
#define mMDebugInfo1( C, ... …Run Code Online (Sandbox Code Playgroud)