在gcc/g ++ 4.*中是否有一种方法可以编写一个扩展为多行的宏?
以下代码:
#define A X \ Y
Run Code Online (Sandbox Code Playgroud)
扩展到
X Y
Run Code Online (Sandbox Code Playgroud)
我需要一个宏扩展到
X
Y
Run Code Online (Sandbox Code Playgroud) 我想知道为什么我们不能在defines 之外使用令牌连接.
当我同时想要这些时,会出现这种情况:
define该则整个代码被合并成一条线,调试器将只显示其中线define使用有些人可能想要一个例子(实际问题在下面):
lib.inc:
#ifndef NAME
#error includer should first define NAME
#endif
void NAME() { // works
}
// void NAME##Init() { // doesn't work
// }
Run Code Online (Sandbox Code Playgroud)
main.c中:
#define NAME conflictfree
#include "lib.inc"
int main(void) {
conflictfree();
// conflictfreeInit();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误:
In file included from main.c:2:0:
lib.h:6:10: error: stray '##' in program
void NAME##Init();
^
Run Code Online (Sandbox Code Playgroud)
经验法则是"仅在定义中连续".如果我没记错的话:原因在于预处理器阶段.问题:为什么它不起作用.阶段参数听起来像曾经是一个实现限制(而不是逻辑原因),然后进入标准.NAME##Init()如果NAME()工作正常可以接受什么?
您认为哪种C宏最有用?我找到了以下一个,用于在C中进行矢量运算:
#define v3_op_v3(x, op, y, z) {z[0]=x[0] op y[0]; \
z[1]=x[1] op y[1]; \
z[2]=x[2] op y[2];}
Run Code Online (Sandbox Code Playgroud)
它的工作方式如下:
v3_op_v3(vectorA, +, vectorB, vectorC);
v3_op_v3(vectorE, *, vectorF, vectorJ);
...
Run Code Online (Sandbox Code Playgroud) 我正在尝试做一个调试系统,但它似乎不起作用.
我想要完成的是这样的事情:
#ifndef DEBUG
#define printd //
#else
#define printd printf
#endif
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?我有很多调试消息,我不想这样做:
if (DEBUG)
printf(...)
code
if (DEBUG)
printf(...)
...
Run Code Online (Sandbox Code Playgroud) 反向工程代码,我对这种风格感到震惊,但我想确保没有充分理由做这些事情....
它只是我还是一种可怕的编码风格
if ( pwbuf ) sprintf(username,"%s",pwbuf->pw_name);
else sprintf(username,"%d",user_id);
Run Code Online (Sandbox Code Playgroud)
为什么包装代码不打算用于编译
#if 0
....
#endif
Run Code Online (Sandbox Code Playgroud)
而不是评论?
编辑:正如下面的一些解释,这是由于flummox/**/的可能性,我没有意识到.
但我仍然不明白,为什么不使用你的编程环境工具或喜欢的文本编辑器的宏来阻止使用"//"注释掉它
难道这不会更直接,更容易知道在视觉上跳过?
我只是缺乏C经验并且错过了为什么这些东西可能是一个好主意 - 或者没有任何借口,我有理由对这段代码的丑陋感到恼火?
有什么理由比较喜欢
#define MY_MACRO() ..stuff..
Run Code Online (Sandbox Code Playgroud)
至
#define MY_MACRO ..stuff..
Run Code Online (Sandbox Code Playgroud)
不要使用宏不是一个有效的答案......
我试着SQR在下面的代码中使用宏的定义:
#define SQR(x) (x*x)
int main()
{
int a, b=3;
a = SQR(b+5); // Ideally should be replaced with (3+5*5+3), though not sure.
printf("%d\n",a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它打印23.如果我将宏定义更改为SQR(x) ((x)*(x))然后输出是预期的,64.我知道在C中调用宏会用宏的定义替换调用,但是我仍然无法理解它是如何计算的23.
如何评估这些宏?
# define i 20
void fun();
int main(){
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
void fun(){
#undef i
#define i 30
}
Run Code Online (Sandbox Code Playgroud)
提供输出为2020但是,
# define i 20
void fun(){
#undef i
#define i 30
}
int main(){
printf("%d",i);
fun();
printf("%d",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出为3030.请解释.谢谢.
我刚刚注意到这一点__func__,__FUNCTION__并__PRETTY_FUNCTION__没有被视为预处理器宏,并且在标准(N4527工作草案)的16.8预定义宏名称部分中没有提到它们.
这意味着它们不能用于阶段6的字符串连接技巧:
// Valid
constexpr char timestamp[]{__FILE__ " has been compiled: " __DATE__ " " __TIME__};
// Not valid!!!
template <typename T>
void die() { throw std::runtime_error{"Error detected in " __PRETTY_FUNCTION__}; }
Run Code Online (Sandbox Code Playgroud)
据我所知,__FILE__,__DATE__并且__TIME__被翻译成由标准规定字符串文字:
16.8预定义的宏名称[cpp.predefined]
__DATE__源文件的转换日期:表单的字符串文字
"Mmm dd yyyy",其中月份的名称与asctime函数生成的月份名称相同,如果值小于dd,则dd的第一个字符是空格字符10.如果没有翻译日期,则应提供实施定义的有效日期.
__FILE__当前源文件的假定名称(字符串文字).
__TIME__源文件的转换时间:表单的字符串文字,
"hh:mm:ss"与asctime函数生成的时间一样.
__func__ 标准提到作为函数本地预定义变量的形式:
static const char __func__[] = "function-name ";
Run Code Online (Sandbox Code Playgroud)
所以事实是,这是一个局部变量,因此字符串连接技巧不适用于它.
至于__FUNCTION__ …
在我的/usr/include目录中,至少有两种#define NULL 0为C++代码1量身定制的变体:
#define NULL 0 // from rpc/types.h
#define NULL (0) // from libio.h
Run Code Online (Sandbox Code Playgroud)
我觉得必须有一个反例,第一个不安全,但我无法生产它.
否则,是否有一些令人信服的论点,说明为什么在这种情况下不包括括号是安全的(例如,非正式的"正确性证明")?
1即,不包括变量#define NULL ((void*)0),它对C有用但在C++中无效.
c-preprocessor ×10
c ×6
c++ ×3
macros ×3
c99 ×1
compilation ×1
debugging ×1
g++ ×1
newline ×1
parentheses ×1
standards ×1