Учитывая следующую программу:
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), по-видимому, отсутствует в любом месте двоичного файла.
Кто-нибудь знает, почему это так?
Потому что он расположен в стеке вызова этой функции. Обычно в подобных случаях одна из двух вещей будет счастливой:
Компилятор будут сохраните эту последовательность в разделе данных, а затем, по существу, запишите ее в буфер стека.
Компилятор, по существу, жестко кодирует команды «перемещения» для повторной сборки последовательности из наибольшего непосредственного значения набора команд (часто это 4-байтовое целое).
Если это не было оптимизировано, как упомянуто «раскрутка», то, вероятно, происходит # 2. Глядя на разборку, пропрограмма (или предварительно собранный ASM-код) покажет вам лучше. использование -S
и посмотрите на файлы .s.
Я думаю, что это неstatic
и автоматический (неглобальный), просто знать, что никто не сможет ссылаться на него извне. Поскольку он не используется, его можно отбросить.
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 тогда только определение 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[]
так что доступ только внутри этого файла и не использовать, так что снова не используется. Но g1[]
является глобальным, это может быть полезно другой программой, если другой файл включает это. И компилятор не допускает оптимизации глобальных объектов.
Ссылка: Как я могу предотвратить компиляцию моих «неиспользуемых» глобальных переменных?
Итак, все это благодаря оптимизации компилятора!