为什么我的const数组存储在堆栈而不是文本部分?

时间:2016-02-25 10:57:52

标签: c arrays const x86-64

我正在实施加密算法(用于教育目的),我发现了一些奇怪的东西。部分算法使用s-box进行替换,因此我将const数组用作查找表,如下所示:

const unsigned char s0_lookup[4][4]={{1,0,3,2},
                                     {3,2,1,0},
                                     {0,2,1,3},
                                     {3,1,3,2}};
const unsigned char s1_lookup[4][4]={{0,1,2,3},
                                     {2,0,1,3},
                                     {3,0,1,0},
                                     {2,1,0,3}};

由于数组使用const限定符,我认为它们应该存储在文本区域而不是堆栈中。但是,如果我对编译器的输出进行反汇编,我会看到:

0000000000000893 <s_des_sbox>:
893:   55                      push   %rbp
894:   48 89 e5                mov    %rsp,%rbp
897:   48 89 7d c8             mov    %rdi,-0x38(%rbp)
89b:   c6 45 dd 00             movb   $0x0,-0x23(%rbp)
89f:   c6 45 e0 01             movb   $0x1,-0x20(%rbp)
8a3:   c6 45 e1 00             movb   $0x0,-0x1f(%rbp)
8a7:   c6 45 e2 03             movb   $0x3,-0x1e(%rbp)
8ab:   c6 45 e3 02             movb   $0x2,-0x1d(%rbp)
8af:   c6 45 e4 03             movb   $0x3,-0x1c(%rbp)
8b3:   c6 45 e5 02             movb   $0x2,-0x1b(%rbp)
8b7:   c6 45 e6 01             movb   $0x1,-0x1a(%rbp)
8bb:   c6 45 e7 00             movb   $0x0,-0x19(%rbp)
8bf:   c6 45 e8 00             movb   $0x0,-0x18(%rbp)
8c3:   c6 45 e9 02             movb   $0x2,-0x17(%rbp)
8c7:   c6 45 ea 01             movb   $0x1,-0x16(%rbp)
8cb:   c6 45 eb 03             movb   $0x3,-0x15(%rbp)
8cf:   c6 45 ec 03             movb   $0x3,-0x14(%rbp)
8d3:   c6 45 ed 01             movb   $0x1,-0x13(%rbp)
8d7:   c6 45 ee 03             movb   $0x3,-0x12(%rbp)
8db:   c6 45 ef 02             movb   $0x2,-0x11(%rbp)
8df:   c6 45 f0 00             movb   $0x0,-0x10(%rbp)
8e3:   c6 45 f1 01             movb   $0x1,-0xf(%rbp)
8e7:   c6 45 f2 02             movb   $0x2,-0xe(%rbp)
8eb:   c6 45 f3 03             movb   $0x3,-0xd(%rbp)
8ef:   c6 45 f4 02             movb   $0x2,-0xc(%rbp)
8f3:   c6 45 f5 00             movb   $0x0,-0xb(%rbp)
8f7:   c6 45 f6 01             movb   $0x1,-0xa(%rbp)
8fb:   c6 45 f7 03             movb   $0x3,-0x9(%rbp)
8ff:   c6 45 f8 03             movb   $0x3,-0x8(%rbp)
903:   c6 45 f9 00             movb   $0x0,-0x7(%rbp)
907:   c6 45 fa 01             movb   $0x1,-0x6(%rbp)
90b:   c6 45 fb 00             movb   $0x0,-0x5(%rbp)
90f:   c6 45 fc 02             movb   $0x2,-0x4(%rbp)
913:   c6 45 fd 01             movb   $0x1,-0x3(%rbp)
917:   c6 45 fe 00             movb   $0x0,-0x2(%rbp)
91b:   c6 45 ff 03             movb   $0x3,-0x1(%rbp)

代码正在移动文字常量来填充堆栈上的空数组!这对我来说似乎非常低效,因为整个数组可以简单地存储为常量。为什么我的代码会这样做?

1 个答案:

答案 0 :(得分:5)

由于它在函数和非静态中声明,因此通常在堆栈上分配。由于C允许递归,因此函数的每次新调用都将获得一个新的数组副本,并在运行时填充。

要在构建时仅初始化一次,您应该将其设置为静态:

static const unsigned char s0_lookup[4][4]={{1,0,3,2},
                                     {3,2,1,0},
                                     {0,2,1,3},
                                     {3,1,3,2}};

因为它被声明为const,所以优化可以使用as-if规则并按照你编写的static const ...编译它,但没有任何东西强迫编译器执行它。