什么是a##b&#a?
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
main()
{
printf("%s\n",h(f(1,2))); //how should I interpret this?? [line 1]
printf("%s\n",g(f(1,2))); //and this? [line 2]
}
Run Code Online (Sandbox Code Playgroud)
这个程序如何运作?
输出是
12
f(1, 2)
Run Code Online (Sandbox Code Playgroud)
现在我明白了如何a##b与#a工作.但为什么两种情况(第1行和第2行)的结果不同?
为什么这些代码块产生不同的结果?
一些常用代码:
#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)
Run Code Online (Sandbox Code Playgroud)
情况1:
#define GLUE(a,b,c) a##b##c
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"
Run Code Online (Sandbox Code Playgroud)
案例2:
#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"
Run Code Online (Sandbox Code Playgroud)
案例3:
#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"
Run Code Online (Sandbox Code Playgroud)
我正在使用VS.net 2005 sp1中的MSVC++
编辑:目前我认为预处理器在扩展宏时的工作方式如下:步骤1: - 取出正文 - 删除##运算符周围的任何空格 - 解析字符串,如果找到的标识符与名称匹配一个参数: - 如果它在##运算符旁边,用参数的文字值(即传入的字符串)替换标识符 - 如果它不在##运算符旁边,则运行整个解释过程首先是参数的值,然后用该结果替换标识符.(忽略stringafy单个'#'case atm) - 删除所有##运算符
第2步: - 获取结果字符串并解析任何宏
现在,我认为所有3个案例都应该产生完全相同的结果字符串:
PART1PART2*
因此,在第2步之后,应该导致
作品*
但至少应该导致同样的事情.
看完VA_NARG后
我尝试使用宏根据C中的参数数量实现函数重载.现在的问题是:
void hello1(char *s) { ... }
void hello2(char *s, char *t) { ... }
// PP_NARG(...) macro returns number of arguments :ref to link above
// does not work
#define hello(...) hello ## PP_NARG(__VA_ARGS__)
int main(void)
{
hello("hi"); // call hello1("hi");
hello("foo","bar"); // call hello2("foo","bar");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我从C-faq那里读到了这个.但仍然无法让它工作......
GNU的cpp允许您将宏参数转换为字符串
#define STR(x) #x
Run Code Online (Sandbox Code Playgroud)
然后,STR(hi)被替换为"hi"
但是,如何将宏(不是宏参数)转换为字符串?
假设我有一个具有某些值的宏CONSTANT,例如
#define CONSTANT 42
Run Code Online (Sandbox Code Playgroud)
这不起作用:STR(CONSTANT).这产生"CONSTANT"的不是我们想要的.
有没有一种简单的方法可以将正则表达式修饰符(如"i")添加到引用的正则表达式中?例如:
$pat = qr/F(o+)B(a+)r/;
$newpat = $pat . 'i'; # This doesn't work
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一方法就是print "$pat\n"回过头来(?-xism:F(o+)B(a+)r)尝试?-xism:用替换去除'i'
它有一个欺骗性的简单代码:
method match(Any:U: |) { self.Str; nqp::getlexcaller('$/') = Nil }
Run Code Online (Sandbox Code Playgroud)
但是,这是它的行为:
(^3).match(1) # OUTPUT: «?1??»
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.
say (1,3 ... * ).match(77); # OUTPUT: «Nil?»
Run Code Online (Sandbox Code Playgroud)
Ooookey.现在发生了什么?
say (1,3 ... * ).match(1); # OUTPUT: «Nil?»
say (1,3 ... * ).match(/\d/); # OUTPUT: «Nil?»
Run Code Online (Sandbox Code Playgroud)
不喜欢序列.
say (^10).match(/\d/); # OUTPUT: «?0??»
Run Code Online (Sandbox Code Playgroud)
好的,再次有意义.
say <a b c>.match(/\w/); # OUTPUT: «?a??»
Run Code Online (Sandbox Code Playgroud)
恢复正常.它不喜欢Seqs吗?我假设,因为我查看了其他类的代码并且match没有重新实现,所有这些代码都调用了代码.但是我没有看到如何返回字符串并从NPQ设置变量,或者为什么它不能用于序列.
我有一个这样的宏(不完全是,但功能相当):
#define STRUCTMEMBER(Member,Value) GlobalStructInstance. ## Member = Value
...
STRUCTMEMBER(Item,1);
Run Code Online (Sandbox Code Playgroud)
这在Visual C++中完美地工作,但是gcc 3.4.5(MingGW)会产生以下错误:
粘贴"." 并且"Item"不提供有效的预处理令牌
当我使用" - >"运算符时也会发生这种情况.我没有找到关于连接的提示,禁止使用这些运算符.
有没有人有想法?
我遇到了一个断言的例子,并想知道它#是为了什么:
#define ASSERT( x ) if ( !( x ) ) { \
int *p = NULL; \
DBGPRINTF("Assert failed: [%s]\r\n Halting.", #x); \
*p=1; \
}
Run Code Online (Sandbox Code Playgroud) 我正在定义一个宏,它计算为一个常量字符串,保存文件名和行号,用于记录目的.
它工作正常,但我无法弄清楚为什么需要2个额外的宏 - STRINGIFY而且TOSTRING,当直觉暗示时__FILE__ ":" #__LINE__.
#include <stdio.h>
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define THIS_ORIGIN (__FILE__ ":" TOSTRING(__LINE__))
int main (void) {
/* correctly prints "test.c:9" */
printf("%s", THIS_ORIGIN);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是一个丑陋的黑客.
具体是什么,这样逐步发生阶段有人能解释__LINE__正确字符串化,为什么既不__FILE__ ":" STRINGIFY(__LINE__)和__FILE__ ":" #__LINE__作品?
我有一个常量定义:
#define MAX_STR_LEN 100
Run Code Online (Sandbox Code Playgroud)
我想这样做:
scanf("%" MAX_STR_LEN "s", p_buf);
Run Code Online (Sandbox Code Playgroud)
但当然这不起作用.
可以使用什么预处理器技巧将MAX_STR_LEN数字转换为字符串,以便我可以在上面的scanf调用中使用它?基本上:
scanf("%" XYZ(MAX_STR_LEN) "s", p_buf);
Run Code Online (Sandbox Code Playgroud)
XYZ()应该是什么?
注意:我当然可以直接做"%100s",但这样做会失败.我也可以#define MAX_STR_LEN_STR"100",但我希望有一个更优雅的解决方案.