例如,如何避免两次写'func_name'?
#ifndef TEST_FUN
# define TEST_FUN func_name
# define TEST_FUN_NAME "func_name"
#endif
Run Code Online (Sandbox Code Playgroud)
我想遵循单点真相规则.
C预处理器的版本:
$ cpp --version
cpp (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)
Run Code Online (Sandbox Code Playgroud) 我知道:
#define foo 4
#define str(s) #s
Run Code Online (Sandbox Code Playgroud)
与str(foo)写出:"foo"因为字符串化的第一个文本扩展的执行,但这样的:
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
Run Code Online (Sandbox Code Playgroud)
与xstr(foo)写出:"4".
为什么?该过程涉及哪些步骤?
#include_next不区分<file>和"file"包含,也不检查您指定的文件是否与当前文件同名.它只是查找名为的文件,从找到当前文件的目录后的搜索路径中的目录开始.使用"#include_next"会导致很大的混乱.我们建议仅在没有其他替代方案时使用.特别是,它不应该用在属于特定程序的标题中; 它应该只用于沿着fixincludes进行全局修正.
那么,有两个问题,#include_next是什么,为什么你需要使用它?
如果有一些代码我想尽可能多地使用C++ 11x扩展,但如果不支持则有后备.目前,GCC的OSX版本和VisualC编译器几乎不支持C++ 11x,所以我使用:
#if (defined(__APPLE__) || (defined(_WIN32)))
...fallback code without C++11x ...
#else
... code using C++11x ...
#endif
Run Code Online (Sandbox Code Playgroud)
这可行,但不是真正正确的事情,特别是因为MacPorts中的gcc编译器支持c ++ 11x.
有#define C11X_SUPPORTED型宏吗?也许GCC只有一些东西?
经常教授的标准数组大小的宏是
#define ARRAYSIZE(arr) (sizeof(arr) / sizeof(arr[0]))
Run Code Online (Sandbox Code Playgroud)
或一些等效的形成.然而,当传入指针时,这种事情会默默地成功,并且在运行时看起来似乎有道理,直到事情神秘地分崩离析.
犯这个错误太容易了:一个具有局部数组变量的函数被重构,将一些数组操作移动到一个以数组作为参数调用的新函数中.
所以,问题是:是否有一个"卫生"宏来检测ARRAYSIZEC中宏的滥用,最好是在编译时?在C++中,我们只使用专门用于数组参数的模板; 在C中,似乎我们需要一些方法来区分数组和指针.(例如,如果我想拒绝数组,我只是(arr=arr, ...)因为数组赋值是非法的).
让我们说由于某种原因你需要写一个宏:MACRO(X,Y). (我们假设您有一个很好的理由不能使用内联函数.) 您希望此宏模拟对没有返回值的函数的调用.
if (x > y)
MACRO(x, y);
do_something();
Run Code Online (Sandbox Code Playgroud)
if (x > y)
MACRO(x, y);
else
MACRO(y - x, x - y);
Run Code Online (Sandbox Code Playgroud)
do_something();
MACRO(x, y)
do_something();
Run Code Online (Sandbox Code Playgroud)
编写宏的天真方式是这样的:
#define MACRO(X,Y) \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl;
Run Code Online (Sandbox Code Playgroud)
这是一个非常糟糕的解决方案,它失败了所有三个例子,我不应该解释原因.
忽略宏实际上做的事情,这不是重点.
现在,我经常看到编写宏的方法是将它们用大括号括起来,如下所示:
#define MACRO(X,Y) \
{ \
cout << "1st arg is:" << …Run Code Online (Sandbox Code Playgroud) 在第一次学习C#时,我很惊讶他们不支持与C/C++相同容量的宏.我意识到#define关键字存在于C#中,但与我在C/C++中的喜爱相比,它非常缺乏.有谁知道为什么C#中缺少真正的宏?
如果这个问题已经以某种形式提出,我很抱歉 - 我保证在发布前花了5分钟时间寻找重复的问题.
考虑以下代码:
#define F(x, ...) X = x and VA_ARGS = __VA_ARGS__
#define G(...) F(__VA_ARGS__)
F(1, 2, 3)
G(1, 2, 3)
Run Code Online (Sandbox Code Playgroud)
X = 1 and VA_ARGS = 2, 3两个宏的预期输出,这就是我用GCC得到的,但是,MSVC将其扩展为:
X = 1 and VA_ARGS = 2, 3
X = 1, 2, 3 and VA_ARGS =
Run Code Online (Sandbox Code Playgroud)
也就是说,__VA_ARGS__将其扩展为单个参数,而不是分解为多个参数.
有什么方法吗?
显然,有些时候#defines必须有括号,如下:
#define WIDTH 80+20
int a = WIDTH * 2; // expect a==200 but a==120
Run Code Online (Sandbox Code Playgroud)
所以我总是括号,即使它只是一个数字:
#define WIDTH (100)
Run Code Online (Sandbox Code Playgroud)
C的新人问我为什么这样做,所以我试图找到一个边缘情况,在一个数字上没有括号#define会导致问题,但我想不出一个.
这种情况是否存在?
我通过Visual Studio 2013预处理器运行以下代码.输出令我惊讶.
hello.cpp的内容:
#define A(j) #j
A(A?)
A(B?)
A(C?)
A(D?)
A(E?)
A(F?)
A(G?)
A(H?)
A(I?)
A(J?)
A(K?)
A(L?)
A(M?)
A(N?)
A(O?)
A(P?)
A(Q?)
A(R?)
A(S?)
A(T?)
A(U?)
A(V?)
A(W?)
A(X?)
A(Y?)
A(Z?)
Run Code Online (Sandbox Code Playgroud)
命令:
cl /P hello.cpp
Run Code Online (Sandbox Code Playgroud)
hello.i包含:
#line 1 "hello.cpp"
"A?"
"B?"
"C?"
"D?"
"E?"
"F?"
"G?"
"H?"
"I?"
"J?"
"K?"
"L"
"M?"
"N?"
"O?"
"P?"
"Q?"
"R"
"S?"
"T?"
"U?"
"V?"
"W?"
"X?"
"Y?"
"Z?"
Run Code Online (Sandbox Code Playgroud)
我试着打电话给A(L?p:q)时碰到了这个,这导致了"Lp:q",这对我不利.
这是正确的,定义明确的C++吗?C++中的L和R有什么特别之处?如果文件具有.c扩展名,则L和R被视为与字母表的其余部分相同.这与C++ 11有关吗?它必须是一个新功能,因为旧版本的MSVS不会以特殊方式使用L和R.
我能做些什么来阻止MSVS 2013以这种特殊方式治疗L和R?
c-preprocessor ×10
c ×4
c++ ×4
gcc ×2
macros ×2
visual-c++ ×2
.net ×1
arrays ×1
c# ×1
c++11 ×1
compiler-bug ×1
dry ×1
include ×1
parentheses ×1