鉴于以下计划:
unsigned char g1[] = { 0x1a, 0x2a, 0x3a, 0x4a };
static unsigned char g2[] = { 0x1b, 0x2b, 0x3b, 0x4b };
int main()
{
unsigned char l1[] = { 0x1c, 0x2c, 0x3c, 0x4c };
static unsigned char l2[] = { 0x1d, 0x2d, 0x3d, 0x4d };
}
之后,简单地用“g ++ test.cpp -o test”编译它并在二进制文件上运行hexdump -C,我意识到g1,g2和l2的序列可以在二进制文件中清楚地找到。只有l1(1c 2c 3c 4c)的序列显然不存在于二进制文件中的任何地方。
有人知道为什么会这样吗?
答案 0 :(得分:4)
因为它是在该函数调用的堆栈上分配的。通常在这种情况下,两件事中的一件会很高兴:
编译器将将该序列存储在数据部分中,然后基本上将其存储到堆栈缓冲区中。
编译器基本上硬编码“移动”指令,以从指令集的最大立即值(通常为4-bye int)重新组装序列。
如果它没有被优化,就像提到的“放松”,那么#2可能正在发生。查看反汇编程序(或预先组装的asm代码)会更好地显示。使用-S
并查看.s文件。
答案 1 :(得分:3)
我的猜测是因为它是非static
和自动(非全局),知道没有人能够从外部引用它是微不足道的。由于它没有被使用,它可以被删除。
答案 2 :(得分:0)
l1[]
和l2[]
,因为它们都是local and unused variables
(两个变量都不会在任何其他位置使用)。
您可以使用-S
选项编译代码以生成汇编代码:并且主要内容中l1[]
和l2[]
没有定义,甚至没有其他地方:
输入文件为x.c
,使用命令gcc -S x.c
进行编译以生成程序集文件x.s
main:
pushl %ebp
movl %esp, %ebp
subl $16, %esp
movb $28, -4(%ebp)
movb $44, -3(%ebp)
movb $60, -2(%ebp)
movb $76, -1(%ebp)
leave
ret
.size main, .-main
.data
.type l2.1250, @object
.size l2.1250, 4
但你可以找到g1[] and g2[]
的定义。
.file "x.c"
.globl g1
.data
.type g1, @object
.size g1, 4
g1:
.byte 26
.byte 42
.byte 58
.byte 74
.type g2, @object
.size g2, 4
g2:
.byte 27
.byte 43
.byte 59
.byte 75
.text
.globl main
.type main, @function
另外,如果您使用标记-O3
优化标志级别3 编译代码,那么知道您是否编译会很有趣,然后只定义{{ 1}}存在。和全局静态变量(文件专用)也被删除。
输入文件为g1[]
,使用命令x.c
进行编译以生成程序集文件gcc -S -O3 x.c
下面:
x.s
.file "x.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.size main, .-main
.globl g1
.data
.type g1, @object
.size g1, 4
g1:
.byte 26
.byte 42
.byte 58
.byte 74
.ident "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5"
.section .note.GNU-stack,"",@progbits
仅显示全局数据,g1[]
中删除了g2[]
。
-O3
使用已定义的g2[]
,因此只能在此文件中访问,而不会再次使用未使用的文件。但static unsigned char g2[]
是全局的,如果其他文件包含它,则其他程序可能会有用。并且不允许编译器优化全局对象。
参考:How do I prevent my 'unused' global variables being compiled out?
所以,这一切都归功于编译器的优化!