在代码审查中,我要求使用下面的选项(1),因为它会导致创建一个符号(用于调试),而(2)和(3)似乎至少对gcc和icc没有这样做。但是(1)不是真正的const,不能在所有编译器上用作数组大小。有没有更好的选项,包括调试符号,并且真正是C的常量?
符号:
gcc f.c -ggdb3 -g ; nm -a a.out | grep _sym
0000000100000f3c s _symA
0000000100000f3c - 04 0000 STSYM _symA
代码:
static const int symA = 1; // 1
#define symB 2 // 2
enum { symC = 3 }; // 3
GDB输出:
(gdb) p symA
$1 = 1
(gdb) p symB
No symbol "symB" in current context.
(gdb) p symC
No symbol "symC" in current context.
为了完整起见,来源:
#include <stdio.h>
static const int symA = 1;
#define symB 2
enum { symC = 3 };
int main (int argc, char *argv[])
{
printf("symA %d symB %d symC %d\n", symA, symB, symC);
return (0);
}
答案 0 :(得分:2)
-ggdb3
选项应该为您提供宏调试信息。但这是一种不同类型的调试信息(它必须是不同的 - 它告诉调试器如何扩展宏,可能包括参数以及#
和##
运算符),这样你就可以了。看到nm
。
如果您的目标是在nm
中显示某些内容,那么我猜您无法使用宏。但这是一个愚蠢的目标;你应该想要一个在调试器中实际工作的东西,对吧?在print symC
中尝试gdb
,看看它是否有效。
由于可以重新定义宏,gdb
要求程序在宏存在的位置停止,以便找到正确的定义。在这个计划中:
#include <stdio.h>
int main(void)
{
#define X 1
printf("%d\n", X);
#undef X
printf("---\n");
#define X 2
printf("%d\n", X);
}
如果您在第一个printf
和print X
上中断,您将获得1; next
到第二个printf
和gdb
会告诉您没有X
;再次next
,它会显示2。
gdb
命令info macro foo
也很有用,如果foo
是一个接受参数的宏,并且您希望查看其定义而不是使用一组特定参数展开它。如果宏扩展为不是表达式的内容,gdb
可以print
,那么info macro
是唯一能用它做的事情。
为了更好地检查原始调试信息,请尝试objdump -W
而不是nm
。
答案 1 :(得分:1)
但是(1)不是真正的const,不能在所有编译器上用作数组大小。
这可以在支持C99和后者(gcc,clang)的所有编译器上用作数组大小。对于其他人(如MSVC),您只有最后两个选项
使用选项3是首选2. enum
s与#define
常量不同。您可以使用它们进行调试。您可以将enum
常量用作l值,与#define
常量不同。