2017-02-13 24 views
4

Я составил следующую программу на 64-битной Linux машине:Почему я не могу найти значение INT в двоичном

#include <stdio.h> 

main() 
{ 
    int a = 12345; 

    if (a == 12346) 
     printf ("YES\n"); 

    return; 
} 

, если я выходе двоичный файл с помощью шестнадцатеричного, я могу найти 12346 (который равен 303a в гексагоне), но не значение 12345 (0x3039). Почему это?

(маленькие или большие байты не должны иметь никакого значения в поиске, что значение)

+2

Почему маленький-vs-big не имеет значения? – Thilo

+0

Я бы ожидал, что компилятор сможет оптимизировать сравнение. Вы уверены, что '0x303a', которое вы находите, является фактическим числом из исходного файла, а не какой-либо другой последовательностью из двух байтов, которая, случается, будет одинаковой? –

+6

Если я сделаю то, что вы описали и скомпилируете с помощью 'gcc main.c', я вижу' 39 30' в смещении 00000538, всего несколько байт до '3A 30'. Если я использую 'gcc -O2 main.c' (например, включите оптимизацию), я не вижу ни одного из них (неудивительно, поскольку все это заканчивается« возвратом »). –

ответ

6

Вот где значения на выходе простого hexdump для меня; посмотрите на выделенные области.

0000500 39fc 0030 8100 fc7d 303a 0000 0a75 a4bf

Если вы ожидали увидеть 3039 как одна группа, которая бы объяснить путаницу. Фактические байты:

fc 39 30 00 00 81 7d fc 3a 30 00 00 75 0a bf a4

Если вы не хотите шестнадцатеричного сделать свой «полезный» выход по умолчанию, где он переосмысливает вход в виде последовательности мало-обратным порядком байтов два байта слова, вы могли бы потратить час выясняя как использовать строки формата или просто выбрать xxd.

4

Самый простой способ ответить на этот вопрос - это скомпилировать его с помощью опции командной строки -S, которая выводит вашу программу на C как код сборки.

Это то, что ваша функция main() компилируется без какой-либо оптимизации (т. Е. С помощью переключателя командной строки -O0). Я удалил некоторые избыточные заявления маркерных и добавил несколько замечаний:

main: 
     leal 4(%esp), %ecx  # Create local storage on stack 
     andl $-16, %esp 
     pushl -4(%ecx) 
     pushl %ebp 
     movl %esp, %ebp 
     pushl %ecx 
     subl $20, %esp 
     movl $12345, -12(%ebp) # Initialize `a` to 12345 
     cmpl $12346, -12(%ebp) # Compare with 12346 
     jne  .L4 
     subl $12, %esp   # If equal, ... 
     pushl $.LC0 
     call puts    # print "YES" 
     addl $16, %esp 
.L4: 
     nop 
     nop 
     movl -4(%ebp), %ecx  # Tidy up and exit 
     leave 
     leal -4(%ecx), %esp 
     ret 

Вы можете увидеть, что номера 12345 и 12346 включены в коде в инструкции movl и cmpl.

С оптимизацией код становится намного проще. Компилятор может видеть, что оператор if никогда не оценивает значение true. Он также может видеть, что переменная a никогда не используется. Это то, что main() выглядит при компиляции с жесткой оптимизацией (-O3):

main: 
     rep ret 

(Примечание: Я составил это на 32-битной Ubuntu дружественного, но точно такая же оптимизация будет происходить на 64-битную машине .)