C:const初始化器和调试符号

时间:2014-03-24 14:25:40

标签: c const declaration

在代码审查中,我要求使用下面的选项(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);
}

2 个答案:

答案 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);
}

如果您在第一个printfprint X上中断,您将获得1; next到第二个printfgdb会告诉您没有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常量不同。