如何在C中字符串化表达式
有没有办法在c中进行字符串化之前评估表达式?
例:
#define stringify(x) #x ... const char * thestring = stringify( 10 * 50 );
问题是我想得到
const char * thestring = "500";
而不是 :
const char * thestring = "10 * 50";
可以这样做吗?
C预处理器不能这样做,所以请改用snprintf
:
char *stringify(int n) { char *res = malloc(12); snprintf(res, 12, "%d", n); return res; }
用法
const char *thestring = stringify(10 * 50);
NB
为简单起见,我省略了错误控制和free
。
您可能不会喜欢表达式的表示forms, 是的 ,它是可能的,但是以一种非常折衷的方式 – 您需要创建一个由预处理器“运行”的单独的函数语言。 证据:
$ cvs -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp login $ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P chaos-pp $ cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P order-pp $ cd order-pp/example $ grep -A 6 'int main' fibonacci.c int main(void) { printf ("The 500th Fibonacci number is " ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0))))) ".\n"); return 0; } $ cpp -I../inc fibonacci.c 2>/dev/null | grep -A 6 'int main' int main(void) { printf ("The 500th Fibonacci number is " "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125" ".\n"); return 0; }
在这个例子中,我们使用新制作的预处理器运行的纯函数语言来计算第500个Fibonacci数,然后将其字符串化以提供给C编译器。
当然,我非常怀疑这是你在实践中曾经使用过的东西,而且它对预处理器的滥用非常紧张,但我认为它是一个非常发人深省的黑客。 (是的,没有像这样的异国情调的理论曲折,这是不可能的)。
我会猜测你在脚本语言方面比在C语言方面有更多的经验。
使用纯编译语言(例如C:Preproccesing,Compiling,Linking和Running)需要注意多个阶段
首先运行预处理器 。 这就是宏扩展的地方。 此时,其内容为“10 * 50”。 没什么可做的。
宏预处理器完成后, 编译器将程序转换为目标文件
编译器在每个源文件上完成后, 链接器会介入并将它们全部打包在一起。
最后,当您的用户准备好后,他们会执行您的程序。 语义上,这是计算10 * 50的时间。 (实际上,大多数编译器都会认识到这将始终是相同的值,并将其替换为500,但这是一个实现细节)。
脚本语言喜欢模糊所有这些行,所以我可以看到有人习惯其中一个的地方可能会混淆。
预处理器宏在编译器之前运行。 根据定义,它不可能完全按照你正在做的事情去做。
要在运行时将数字转换为字符串,请调用itoa
函数,如下所示:
char thestring[8]; itoa(10 * 50, thestring, 10);
请注意,此代码将thestring
声明为数组,而不是指针。 有关更多信息,请阅读C中的内存管理。
你需要解释字符串。 C本身并不这样做,查找一个可以为你做的库。
http://expreval.sourceforge.net/ http://www.codeproject.com/KB/library/expreval.aspx
还有其他人,只是搜索谷歌。
您可以编写一个脚本(perl?)来用作预处理器,它可以识别要评估的字符串,对它们进行评估,然后在“已评估”文件中调用真正的cpp。
也许它可以工作。
正如其他回复所说,使用C预处理器无法做到这一点。 这是C语言解决的C的许多缺点之一,这是可以使用模板元编程以非常优雅的方式完成的事情。
要在编译时计算算术表达式:
#include namespace mpl = boost::mpl; int main(int argc, char *argv[]) { const int n = mpl::multiplies, mpl::int_<50> >::value; return 0; }
这是我在boost邮件列表档案中找到的字符串格式化元函数 。 此版本将int(如上面计算的那个)转换为您选择的基础中的字符串:
#include #include #include #include #include #include #include #include namespace mpl = boost::mpl; struct itoa_ct { // radix for _itoa() goes up to 36, but only bother with 16 here typedef mpl::vector_c radix_t; template struct radix_convert { typedef typename mpl::push_back< typename radix_convert::type , mpl::char_::type::value> >::type type; }; template struct radix_convert { typedef mpl::string<> type; }; template struct apply { // All bases != 10 consider I as unsigned typedef typename radix_convert< Radix, static_cast((Radix == 10 && I < 0) ? -I : I) >::type converted_t; // Prefix with '-' if negative and base 10 typedef typename mpl::if_< mpl::bool_<(Radix == 10 && I < 0)> , mpl::push_front > , mpl::identity >::type::type type; }; };
将两者放在一起表达式变为:
const char *thestring = mpl::c_str, mpl::int_<50> >::value>::type>::value;
…在编译时这一切都变成了一个常量字符串“500”:-)