相关疑难解决方法(0)

使用##和__LINE__创建C宏(使用定位宏进行标记连接)

我想创建一个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)

这可能吗?

(是的,无论这看起来多么无用,我都有一个真正的理由要这样做).

c macros concatenation token

103
推荐指数
1
解决办法
6万
查看次数

##预处理器运算符和陷阱的应用有哪些应用?

正如我之前的许多问题所述,我正在通过K&R工作,目前正在进入预处理器.其中一个更有意思的事情 - 我之前从未尝试过的任何学习C的尝试 - 是##预处理器操作员.根据K&R的说法:

预处理器运算符## 提供了一种在宏扩展期间连接实际参数的方法.如果替换文本中##的参数与a相邻,则参数将替换为实际参数, ##并删除周围的空白区域,并重新扫描结果.例如,宏paste 连接其两个参数:

#define paste(front, back) front ## back

所以paste(name, 1)创建令牌 name1.

如何以及为什么有人会在现实世界中使用它?它的使用的实际例子是什么,有什么需要考虑的?

c kernighan-and-ritchie stringification c-preprocessor

86
推荐指数
4
解决办法
7万
查看次数

预处理程序令牌扩展

我对预处理器如何工作的心理模型显然是不完整的,这让我发疯.

我想连接两个标记,但第二个标记应该首先扩展.

#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.目前,这对我来说似乎很神奇.

任何人都可以向我解释这种行为吗?扩展规则如何正常工作?

c c++ c-preprocessor

15
推荐指数
1
解决办法
7750
查看次数

宏中的双哈希(##)是什么意思?

在下面的代码中,该##怎么办?

 #define MAKE_TYPE(myname) \
 typedef int myname ## Id; \
Run Code Online (Sandbox Code Playgroud)

c c++

12
推荐指数
2
解决办法
1888
查看次数

在##连接之前评估预处理程序令牌

我想在它与其他东西连接之前评估一个令牌."问题"是标准将行为指定为

在重新检查替换列表以更换更多宏名称之前,删除替换列表中的##预处理标记的每个实例(不是来自参数),并将前面的预处理标记与以下预处理标记连接起来.

因此在下面的例子中,

#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)

c string-concatenation stringification c-preprocessor

11
推荐指数
2
解决办法
3128
查看次数

在宏中使用#

请解释一下代码

#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宏的包装?

c macros preprocessor-directive

11
推荐指数
2
解决办法
1593
查看次数

C宏 - 动态#include

我试图弄清楚如何使用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语句缺少引号..任何想法?

c macros include c-preprocessor

9
推荐指数
2
解决办法
1万
查看次数

使用C预处理器连接以指数表示法获取数字

为什么代码:

#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被解析为两个标记(?).但是,在这种情况下如何获得后者的结果呢?

concatenation c-preprocessor

8
推荐指数
1
解决办法
1065
查看次数

使用VS 2008和GCC时对__VA_ARGS__的不同处理问题

我试图找出一个问题,因为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可变参数宏的正确解释?或者我的用法属于未定义的行为?

gcc visual-studio-2008

7
推荐指数
2
解决办法
1921
查看次数

如何在粘贴之前保证参数的完全宏扩展?

我有一个普通的宏:

#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)

c++ macros c-preprocessor

7
推荐指数
1
解决办法
3032
查看次数