至少有一些C预处理器允许你将宏的值(而不是它的名称)通过一个类似函数的宏传递给另一个将它串行化的宏来进行字符串化:
#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */
Run Code Online (Sandbox Code Playgroud)
这里的用例示例.
这确实有效,至少在GCC和Clang(两者都有-std=c99),但我不确定它是如何工作的C标准术语.
这种行为是否由C99保证?
如果是这样,C99如何保证呢?
如果不是,那么从C定义到GCC定义的行为在什么时候?
我是Objective-C的新手,我有一些关于const和预处理指令的问题#define.
首先,我发现无法使用定义常量的类型#define.这是为什么?
第二,使用其中一个比另一个更有优势吗?
最后,哪种方式更有效和/或更安全?
我试图找出如何使用C预处理器将#define'd int 连接到#define'字符串.我的编译器是CentOS 5上的GCC 4.1.该解决方案也适用于MinGW.
我想在字符串上附加一个版本号,但我能让它工作的唯一方法是将版本号的副本定义为字符串.
我能找到的最接近的东西是引用宏参数的方法,但它不适用于#defines
这不起作用.
#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER
Run Code Online (Sandbox Code Playgroud)
它不没有工作,#小号或者是因为值为数字,它会扩大到"/home/user/.myapp" 2 6,这是无效的Ç.
这确实有效,但我不喜欢有版本定义的副本,因为我确实需要它们作为数字.
#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING
Run Code Online (Sandbox Code Playgroud) 我必须在C中做这样的事情.它只有在我使用char时才有效,但我需要一个字符串.我怎样才能做到这一点?
#define USER "jack" // jack or queen
#if USER == "jack"
#define USER_VS "queen"
#elif USER == "queen"
#define USER_VS "jack"
#endif
Run Code Online (Sandbox Code Playgroud) 我对c ++中的预处理器指令有疑问:
例如:
#ifndef QUESTION
//some code here
#ifndef QUESTION
//some code here
#endif
#endif
Run Code Online (Sandbox Code Playgroud)
利用它我们可以用这种方式,并且可以在C++编译器的匹配ifndef,并endif以正确的方式?
#define DEFINE_STAT(Stat) \
struct FThreadSafeStaticStat<FStat_##Stat> StatPtr_##Stat;
Run Code Online (Sandbox Code Playgroud)
上面这行来自虚幻4,我知道我可以在不真实的论坛上问过它,但我认为这是一个普遍的C++问题,值得在这里提出.
我理解第一行定义了一个宏,但是我不熟悉C++中的预处理器恶作剧,所以我迷失在那里.逻辑告诉我反斜杠意味着声明继续到下一行.
FThreadSafeStaticStat看起来有点像模板,但是那里正在进行#和C++中我从未见过的语法
有人能告诉我这意味着什么吗?我知道您可能无法访问Unreal 4,但这只是我不理解的语法.
当我在一个充满宏技巧和魔法的大项目中工作时,我偶然发现了一个错误,其中宏没有正确扩展。结果输出是“ EXPAND(0)”,但EXPAND被定义为“ #define EXPAND(X) X”,所以显然输出应该是“ 0”。
“没问题”,我心里想。“这可能是一些愚蠢的错误,这里有一些令人讨厌的宏,毕竟有很多地方会出错”。正如我所想的那样,我将行为不当的宏隔离到他们自己的项目中,大约 200 行,并开始使用 MWE 来查明问题。200 行变成了 150,然后又变成了 100,然后是 20、10……令我震惊的是,这是我最后的 MWE:
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
EXPAND(TEST PARENTHESIS()) // EXPAND(0)
Run Code Online (Sandbox Code Playgroud)
4 行。
雪上加霜的是,几乎对宏的任何修改都会使它们正常工作:
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
// Manually replaced PARENTHESIS()
EXPAND(TEST ()) // 0
Run Code Online (Sandbox Code Playgroud)
#define EXPAND(X) X
#define PARENTHESIS() ()
#define TEST() EXPAND(0)
// Manually replaced TEST()
EXPAND(EXPAND(0)) // 0
Run Code Online (Sandbox Code Playgroud)
// Set EXPAND to 0 instead of X
#define …Run Code Online (Sandbox Code Playgroud) 在C++中,是这样的:
#ifdef A && B
Run Code Online (Sandbox Code Playgroud)
同样如下:
#if defined(A) && defined(B)
Run Code Online (Sandbox Code Playgroud)
?
我当时认为它不是,但我无法找到与我的编译器(VS2005)的差异.
我试图弄清楚如何编写一个宏,将一个变量名称的字符串文字表示与变量本身一起传递给一个函数.
例如,给出以下功能.
void do_something(string name, int val)
{
cout << name << ": " << val << endl;
}
Run Code Online (Sandbox Code Playgroud)
我想写一个宏,所以我可以这样做:
int my_val = 5;
CALL_DO_SOMETHING(my_val);
Run Code Online (Sandbox Code Playgroud)
哪个会打印出来: my_val: 5
我尝试过以下操作:
#define CALL_DO_SOMETHING(VAR) do_something("VAR", VAR);
Run Code Online (Sandbox Code Playgroud)
但是,正如您可能猜到的那样,引号内的VAR不会被替换,而只是作为字符串文字"VAR"传递.所以我想知道是否有办法让宏参数变成字符串文字本身.
我来自脚本背景,C中的预处理器对我来说总是很难看.然而,当我学习编写小型C程序时,我已经接受了它.我只是真的使用预处理器来包含我为自己的函数编写的标准库和头文件.
我的问题是为什么C程序员不会跳过所有包含并简单地连接他们的C源文件然后编译它?如果将所有包含放在一个位置,则只需要定义一次所需内容,而不是在所有源文件中定义.
这是我所描述的一个例子.这里我有三个文件:
// includes.c
#include <stdio.h>
Run Code Online (Sandbox Code Playgroud)
// main.c
int main() {
foo();
printf("world\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
// foo.c
void foo() {
printf("Hello ");
}
Run Code Online (Sandbox Code Playgroud)
通过cat *.c > to_compile.c && gcc -o myprogram to_compile.c在我的Makefile中执行某些操作,我可以减少我编写的代码量.
这意味着我不必为我创建的每个函数编写头文件(因为它们已经在主源文件中),这也意味着我不必在我创建的每个文件中包含标准库.这对我来说似乎是一个好主意!
但是我意识到C是一种非常成熟的编程语言,我想象的是比我聪明的其他人已经有了这个想法,并决定不使用它.为什么不?
c-preprocessor ×10
c ×6
c++ ×4
compilation ×1
conditional ×1
const ×1
macros ×1
objective-c ×1