替代标题(以帮助搜索)
- 将预处理程序标记转换为字符串
- 如何从C宏的值创建一个char字符串?
我想在编译时使用C #define来构建文字字符串.
该字符串是为调试,发布等而更改的域.
我想要一些这样的事情:
#ifdef __TESTING
#define IV_DOMAIN domain.org //in house testing
#elif __LIVE_TESTING
#define IV_DOMAIN test.domain.com //live testing servers
#else
#define IV_DOMAIN domain.com //production
#endif
// Sub-Domain
#define IV_SECURE "secure.IV_DOMAIN" //secure.domain.org etc
#define IV_MOBILE "m.IV_DOMAIN"
Run Code Online (Sandbox Code Playgroud)
但预处理器不评估""内的任何内容
#include <stdio.h>
#define f(a,b) a##b
#define g(a) #a
#define h(a) g(a)
int main()
{
printf("%s\n",h(f(1,2)));
printf("%s\n",g(f(1,2)));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
只需通过查看程序,"可能"期望输出,对于两个printf语句都是相同的.但是在运行程序时,你得到它:
bash$ ./a.out
12
f(1,2)
bash$
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
在我们的遗留代码中,以及我们的现代代码中,我们使用宏来执行代码生成等的漂亮解决方案.我们同时使用#和##运算符.
我很好奇其他开发人员如何使用宏来做很酷的事情,如果他们根本使用它们的话.
我在构建设置中定义了预处理器宏
FOO=BAR
Run Code Online (Sandbox Code Playgroud)
我希望将这个值按到一个可以传递给方法的Objective-C字符串文字中.以下#define不起作用,但它应该展示我想要实现的目标:
#define FOOLITERAL @"FOO" //want FOOLITERAL to have the value of @"BAR"
myMethodThatTakesAnNSString(FOOLITERAL);
Run Code Online (Sandbox Code Playgroud)
我希望我只是在某种程度上错过了显而易见的东西,但我似乎无法找到合适的预处理器伏都教来获得我需要的东西.
cocoa cocoa-touch objective-c stringification c-preprocessor
我希望有一种方法可以将#include指令分成两行,这样我的代码就可以符合每行80个字符,尽管需要很长的包含路径.
除了扩展编译器的搜索路径之外,我该如何管理呢?有没有办法将我的长路径字符串分成两行?
"#define"宏扩展显然发生在#include扩展之后,所以这些不起作用:
#define BIGPATH "..."
#include BIGPATH ## "/foo.c"
#include "BIGPATH/foo.c"
#include BIGPATH"/foo.c"
Run Code Online (Sandbox Code Playgroud)
我也试过了
#include "foo" ##
"bar"
Run Code Online (Sandbox Code Playgroud)
和
#include "foo" \
"bar"
Run Code Online (Sandbox Code Playgroud)
无济于事.也许我想要的是不可能的?帮助我,stackoverflow kenobi,你是我唯一的希望.
答案:建立在下面的建议答案上,这是实际对我有用的:
#define STRINGIFY(x) #x
#define PATH(path) STRINGIFY(/my/very/long/path)
#include PATH(foo.h)
#undef PATH
#undef STRINGIFY
Run Code Online (Sandbox Code Playgroud) 注意:这个问题与OpenCL本身无关......请查看最后一段,以获得我的问题的简洁陈述.但要提供一些背景知识:
我正在编写一些使用OpenCL的C++代码.我喜欢将OpenCL内核的源代码保存在自己的文件中,以保持编码和维护的简单性(而不是将源代码直接嵌入到相关C++代码中的字符串常量中).这一问题不可避免地导致了一旦分配二进制文件时如何将它们加载到OpenCL运行时的问题 - 理想情况下,OpenCL源包含在二进制文件中,因此二进制文件不需要在特定的位置在一些目录结构中,知道OpenCL源代码的位置.
我想将OpenCL文件作为字符串常量包含在某处,最好不使用额外的构建步骤或外部工具(对于交叉编译器/跨平台易用性...即,不xxd等等).我以为我偶然发现了一个基于这个帖子中第二个答案的技术,就像这样:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels = STRINGIFY(
#include "kernels/util.cl"
#include "kernels/basic.cl"
);
return kernels;
}
Run Code Online (Sandbox Code Playgroud)
请注意,STRINGIFY如果可能的话,我宁愿不在我的OpenCL代码中嵌入宏(如上面引用的SO问题中所做的那样).现在,这在Clang/LLVM编译器上运行得非常好,但是GCC死了一个可怕的死亡("未终止的参数列表调用宏STRINGIFY"和与.cl文件的内容相关的各种语法"错误"出现).所以,很明显这个确切的技术在编译器中是不可用的(没有尝试过MSVC,但我也希望它能在那里工作)...我怎么能最低限度地按摩它以便它可以在编译器中工作?
总之,我想要一种符合标准的技术,将文件内容作为C/C++字符串常量包含在内,而无需调用外部工具或使用无关代码污染文件.想法?
编辑:正如Potatoswatter指出的那样,上面的行为是未定义的,所以一个真正的交叉编译器预处理器技术不涉及触摸要被字符串化的文件可能是不可能的(第一个找出令人发指的人)黑客工具,做的工作对大多数/所有的编译器得到的答案要点).对于好奇的,最后我做什么在第二个响应建议在这里 ......也就是说,我添加了STRINGIFY直接宏OpenCL的文件,我包括:
在somefile.cl:
STRINGIFY(
... // Lots of OpenCL code
)
Run Code Online (Sandbox Code Playgroud)
在somefile.cpp:
#define STRINGIFY(src) #src
inline const char* Kernels() {
static const char* kernels =
#include "somefile.cl"
;
return kernels;
}
Run Code Online (Sandbox Code Playgroud)
这在我尝试过的编译器中起作用(Clang和GCC也是如此,因为它在宏内部没有预处理器指令),并且至少在我的上下文中并没有太大的负担(即,它没有' t干扰语法高亮/编辑OpenCL文件).像这样的预处理器方法的一个特点是,由于相邻的字符串被连接起来,你可以写
inline const …Run Code Online (Sandbox Code Playgroud) 我已经意识到(艰难的方法)eq当操作数之一是具有重载字符串化的对象时,运算符会给出致命的运行时错误.
这是一个最小的例子:
my $test = MyTest->new('test');
print 'yes' if $test eq 'test';
package MyTest;
use overload '""' => sub { my $self = shift; return $self->{'str'} };
sub new {
my ( $class, $str ) = @_;
return bless { str => $str }, $class;
}
Run Code Online (Sandbox Code Playgroud)
运行它的结果是:
Operation "eq": no method found,
left argument in overloaded package MyTest,
right argument has no overloaded magic at ./test.pl line 7.
Run Code Online (Sandbox Code Playgroud)
我对阅读perlop的期望是在两个操作数上强制使用字符串上下文,触发字符串化方法$test,然后比较结果字符串.为什么不起作用?什么是实际的hapenning?
我遇到这个问题的上下文是在一个使用autodie和的脚本中Try::Tiny.在 …
如果我在GCC_PREPROCESSOR_DEFINITIONS(或预处理器宏,如果你使用XCode)下添加一个宏"FOO = bar",那么访问"FOO"值的最佳方法是什么?
目前,我使用笨拙的:
#define MACRO_NAME(f) #f
#define MACRO_VALUE(f) MACRO_NAME(f)
#ifdef FOO
NSLog(@"%s", MACRO_VALUE(FOO));
#else
NSLog(@"undefined");
#endif
Run Code Online (Sandbox Code Playgroud)
这将输出"bar"
当然,必须有更好/更清洁的方式?
为什么这不产生任何东西?
console.log(JSON.stringify(function(){console.log('foobar');}));
Run Code Online (Sandbox Code Playgroud) 我有一个C程序如下:
#define f(g,g2) g##g2
main()
{
int var12=100;
printf("%d",f(var,12));
}
Run Code Online (Sandbox Code Playgroud)
当我只运行预处理器时,它将其扩展为
{
int var12=100;
printf("%d",var12);
}
Run Code Online (Sandbox Code Playgroud)
这就是输出为100的原因.
谁能告诉我预处理器如何扩展var##12 to var12?
stringification ×10
c ×5
c++ ×2
include ×2
macros ×2
objective-c ×2
cocoa ×1
cocoa-touch ×1
function ×1
javascript ×1
json ×1
opencl ×1
perl ×1
xcode ×1