2013-09-11 2 views
-1
#include <stdio.h> 

void fun3(int a, int b, int c) 
{ 
    printf("%d \n", a+b+c); 
} 
void fun2 (int x, int y) 
{ 
    fun3(0x33333333,0x30303030, 0x31313131); 
    printf("%d \n", x+y); 
} 
fun1 (int x) 
{ 
    fun2(0x22222222,0x20202020); 
    printf("%d \n", x); 
} 
main() 
{ 
    fun1(0x1111111); 
} 

Я просматриваю вышеуказанную программу для повреждения стека. Я получаю o/p для вышеуказанной программы с некоторыми нежелательными значениями. Все, что я мог понять, это если добавленное значение превышает 0xFFFFFFFF, тогда небольшое отрицательное целое число становится наибольшим значением, например -1 становится 0xFFFFFFFF. Любые идеи по этомуДобавление знакового целого числа за пределами 0xFFFFFFFF

+1

Делитесь неожиданными значениями, которые вы видите, а также значениями, которые вы ожидаете? –

+5

Подписанное целочисленное переполнение - это неопределенное поведение, но, скорее всего, вы видите сплошное переполнение целых чисел [2-го дополнения] (http://en.wikipedia.org/wiki/Two's_complement). – Cornstalks

+3

Не уверен, как коррупция в стеке играет в это. Кажется, что в этой программе нет никакого повреждения стека. Кроме того, неясно, каков ваш вопрос. –

ответ

2

до точки @Cornstalks': INT_MIN является 0x80000000 и (int)-1 является 0xFFFFFFFF в дополнение до 2 (на 32-битной системе, в любом случае).

Это позволяет набор команд, чтобы делать вещи в знаковой арифметики, как:

1 + -2 = -1 

становится (как знаковые short с, для краткости)

0x0001 + 0xFFFE = 0xFFFF 

... потом:

1 + -1 = 0 

представлен внутренним переполнением как

0x0001 + 0xFFFF = 0x0000 

Также к точке @Cornstalks: внутреннее представление (а также добавление переполнения) представляет собой деталь реализации. C (и наборы инструкций) не должны представлять целые числа в дополнении 2, поэтому предоставление шестнадцатеричных значений для целых типов со знаком может привязать вас к подмножеству реализаций C.

+0

Точка @ pablo1977: если вы перепечатали все свои 'int' как 'unsigned int' и использовали '% u' вместо'% d' в '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' –

2

EDIT (исправления) (я пропустил точку. Мой ответ является правильным для констант, но вопрос содержит параметры функций, то, что здесь происходит переполнение подписанных целых объектов и, как правильно указало @Cornstalks в его комментарий, это неопределенное поведение). /EDIT

В fun1() вы используете printf() в неправильном направлении.
Вы написали "%d", чтобы принять int, но это неправда, если ваш номер больше, чем MAX_INT.

В вашей системе необходимо проверить значение MAX_INT.
Если вы пишете целую постоянный в шестнадцатеричном формате, стандарт C (ISO C99 или C11) пытается поставить значение в первом типе, что константа может соответствовать, следуя порядку:

Int , unsigned int, long int, unsigned long int, long long int, unsigned long long int.

Таким образом, если у вас есть постоянная больше, что MAX_INT (макс. Значение в диапазоне int), ваш постоянный (если положительный) имеет тип unsigned int, но директива %d ожидается значение signed int. Таким образом, будет показано некоторое отрицательное число.

Худший, если ваша постоянная величина больше UMAX_INT (макс.значение в диапазоне unsigned int), тогда тип константы будет первым из long int, unsigned long int, long long int, с точностью, строго превышающей unsigned int.
Это означает, что %d становится неправильной директивой.

Если вы не можете быть полностью уверены, насколько велики будут ваши ценности, вы могли бы сделать бросок к самому большому целочисленному типу:

printf("%lld", (long long int) 0x33333333333); 

директива %lld обозначает long long int.
Если вы заинтересованы всегда положительные значения, вы должны использовать %llu и приведение к unsigned long long int:

printf("%llu", (unsigned long long int) 0x33333333333); 

Таким образом, вы избежать каких-либо «смешные» номера, так же, как вы показать большие цифры без потери любой точности.

Примечание: константы INT_MAX, UINT_MAX и тому подобное, в limits.h.

Важно: Автоматическая последовательность слепок действительна только для восьмеричных и шестнадцатеричных констант. Для десятичных констант существует другое правило:

int, long int, long long int.

+0

Я исправил свой ответ, потому что не подходит хорошо в вопросе. Код вопроса задает параметры 'int', поэтому комментарий @Cornstalks (на вопрос) применяется. Тем не менее, я думаю, что интересно понять, что делает компилятор с целыми константами. – pablo1977

1

fun3 попытается распечатать значение 0x94949494. Это больше, чем максимальное 4-байтовое целочисленное значение 0x7FFFFFFF, поэтому оно будет «переполняться» и (фактически на каждом компьютере, произведенном сегодня), произведет (если бы я правильно выполнило мою арифметику) отрицательное число -0x6B6B6B6C, которое равно -1802201964.

fun1 и fun2 должны печатать «ожидаемые» положительные результаты.

Смежные вопросы