有没有办法让C编译器(在我的情况下是XC16,基于gcc)转储编译时表达式的结果?
我们有很多#defines,比如
#define FOO 37.6
#define FOO_BASE 0.035
#define FOO_FIXEDPOINT (int16_t)(FOO/FOO_BASE)
我想知道编译器将这些表达式减少到的实际数字。
请注意, NOT 与想知道预处理器输出的内容相同;预处理器不计算数学,它只能替代事物。如果我查看预处理器输出,我得到(有效)
#define FOO_FIXEDPOINT (int16_t)(37.6/0.035)
并且它是编译器,而不是预处理器,它会计算出一个值。
另一个重要的一点是:我可以自由地创建一个特殊的.c文件来完成像
这样的事情#include "foo.h"
const int16_t foo_fixedpoint = FOO_FIXEDPOINT;
这样我就可以为编译器提供一个工作位置并将结果作为常量。
就像一个完整的自包含示例一样,如果我将它放入foo.c并运行xc16-gcc.exe -E foo.c
:
#include <stdint.h>
#define FOO 37.6
#define FOO_BASE 0.035
#define FOO_FIXEDPOINT (int16_t)(FOO/FOO_BASE)
int main()
{
int x = FOO_FIXEDPOINT;
}
我得到了这个输出:
[... typedefs elided ...]
int main()
{
int x = (int16_t)(37.6/0.035);
}
答案 0 :(得分:16)
查看debugging options页面中的标记-fdump-tree-*
,以查看中间语言的输出(有点低级但非常易读)。
您可以使用-fdump-tree-all
在不同阶段查看文件,但可能只需要-fdump-tree-original
。在生成的*.original
文件中向下查看以查找您的主要功能:
...
;; Function main (null)
;; enabled by -tree-original
{
int x = 1074;
int x = 1074;
}
答案 1 :(得分:2)
正如评论中所讨论的,特别是如果数字宏没有与具有非数字类型的宏混合,则生成打印其值的程序很简单。
即使您的环境是交叉编译器,这也是一个有用的练习,因为所有gcc都在内部使用相同的代码处理常量表达式。这会以扩展精度进行数学运算,以便编译常量在精确值的一个ULP内。
因此,任何gcc都应该准确了解代码的内容。
在perl:
print "#include<stdio.h>\n";
print "#include \"$ARGV[0]\"\n";
print "#define S(X) #X\n";
print "int main(void) {\n";
open F, $ARGV[0] or die $!;
while (<F>) {
print " printf(\"%s=%.13g\\n\", S($1), (double)$1);\n" if /#define\s+(\w+)\s+\S/;
}
print " return 0;\n}\n";
现在通过math.h
运行来试试。
perl /usr/include/math.h > math_h_syms.c
这会产生:
#include<stdio.h>
#include "/usr/include/math.h"
#define S(X) #X
int main(void) {
printf("%s=%.13g\n", S(INFINITY), (double)INFINITY);
printf("%s=%.13g\n", S(FP_NAN), (double)FP_NAN);
printf("%s=%.13g\n", S(FP_INFINITE), (double)FP_INFINITE);
printf("%s=%.13g\n", S(FP_ZERO), (double)FP_ZERO);
printf("%s=%.13g\n", S(FP_NORMAL), (double)FP_NORMAL);
printf("%s=%.13g\n", S(FP_SUBNORMAL), (double)FP_SUBNORMAL);
printf("%s=%.13g\n", S(FP_SUPERNORMAL), (double)FP_SUPERNORMAL);
printf("%s=%.13g\n", S(FP_ILOGB0), (double)FP_ILOGB0);
printf("%s=%.13g\n", S(FP_ILOGBNAN), (double)FP_ILOGBNAN);
printf("%s=%.13g\n", S(MATH_ERRNO), (double)MATH_ERRNO);
printf("%s=%.13g\n", S(MATH_ERREXCEPT), (double)MATH_ERREXCEPT);
printf("%s=%.13g\n", S(math_errhandling), (double)math_errhandling);
printf("%s=%.13g\n", S(M_E), (double)M_E);
printf("%s=%.13g\n", S(M_LOG2E), (double)M_LOG2E);
printf("%s=%.13g\n", S(M_LOG10E), (double)M_LOG10E);
printf("%s=%.13g\n", S(M_LN2), (double)M_LN2);
printf("%s=%.13g\n", S(M_LN10), (double)M_LN10);
printf("%s=%.13g\n", S(M_PI), (double)M_PI);
printf("%s=%.13g\n", S(M_PI_2), (double)M_PI_2);
printf("%s=%.13g\n", S(M_PI_4), (double)M_PI_4);
printf("%s=%.13g\n", S(M_1_PI), (double)M_1_PI);
printf("%s=%.13g\n", S(M_2_PI), (double)M_2_PI);
printf("%s=%.13g\n", S(M_2_SQRTPI), (double)M_2_SQRTPI);
printf("%s=%.13g\n", S(M_SQRT2), (double)M_SQRT2);
printf("%s=%.13g\n", S(M_SQRT1_2), (double)M_SQRT1_2);
printf("%s=%.13g\n", S(MAXFLOAT), (double)MAXFLOAT);
printf("%s=%.13g\n", S(FP_SNAN), (double)FP_SNAN);
printf("%s=%.13g\n", S(FP_QNAN), (double)FP_QNAN);
printf("%s=%.13g\n", S(HUGE), (double)HUGE);
printf("%s=%.13g\n", S(X_TLOSS), (double)X_TLOSS);
printf("%s=%.13g\n", S(DOMAIN), (double)DOMAIN);
printf("%s=%.13g\n", S(SING), (double)SING);
printf("%s=%.13g\n", S(OVERFLOW), (double)OVERFLOW);
printf("%s=%.13g\n", S(UNDERFLOW), (double)UNDERFLOW);
printf("%s=%.13g\n", S(TLOSS), (double)TLOSS);
printf("%s=%.13g\n", S(PLOSS), (double)PLOSS);
return 0;
}
编译并运行:
INFINITY=inf
FP_NAN=1
FP_INFINITE=2
FP_ZERO=3
FP_NORMAL=4
FP_SUBNORMAL=5
FP_SUPERNORMAL=6
FP_ILOGB0=-2147483648
FP_ILOGBNAN=-2147483648
MATH_ERRNO=1
MATH_ERREXCEPT=2
math_errhandling=2
M_E=2.718281828459
M_LOG2E=1.442695040889
M_LOG10E=0.4342944819033
M_LN2=0.6931471805599
M_LN10=2.302585092994
M_PI=3.14159265359
M_PI_2=1.570796326795
M_PI_4=0.7853981633974
M_1_PI=0.3183098861838
M_2_PI=0.6366197723676
M_2_SQRTPI=1.128379167096
M_SQRT2=1.414213562373
M_SQRT1_2=0.7071067811865
MAXFLOAT=3.402823466385e+38
FP_SNAN=1
FP_QNAN=1
HUGE=3.402823466385e+38
X_TLOSS=1.414847550406e+16
DOMAIN=1
SING=2
OVERFLOW=3
UNDERFLOW=4
TLOSS=5
PLOSS=6
答案 2 :(得分:1)
编辑这不起作用: - (
即使有将整数转换为字符串的技巧,预处理器也不会评估组合值。
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define A 1
#define B 2
#define C A+B
#pragma message("A=" STR(A))
#pragma message("B=" STR(B))
#pragma message("C=" STR(C))
编译器输出(VS2008):
1>A=1
1>B=2
1>C=1+2
所以预处理器在这里没有帮助。
原始答案 作为最后的手段,如果无法通过gcc-options等获取中间文件中的值。
我会查找#define的源文件,将输出重定向到新的.c文件中,并将#define替换为#pragma message
。在此文件上调用gcc将列出所有定义。原因是您的编译器支持#pragma message
。