如何在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”:-)