2017-02-21 2 views
2

При работе через упражнение 3-5 в Язык программирования C, я столкнулся с следующим неожиданным поведением.Почему переменная мутируется в программе C?

#include <stdio.h> 
#include <string.h> 

// inspired by: http://www.eng.uerj.br/~fariasol/disciplinas/LABPROG/C_language/Kernighan_and_Ritchie/solved-exercises/solved-exercises.html/krx305.html 

void reverse(char s[]) { 
    int c, i, j; 
    for (i = 0, j = strlen(s)-1; i < j; i++, j--) { 
     c = s[i]; 
     s[i] = s[j]; 
     s[j] = c; 
    } 
} 

void itob(int n, char s[], int b) { 
    static char digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 
    int i = 0, 
     sign; 

    if (b < 2 || b > 36) { 
     fprintf(stderr, "EX3_5: Cannot support base %d\n", b); 
    } 

    if ((sign = n) < 0) { 
     n = -n; 
    } 

    do { 
     s[i++] = digits[n % b]; 
    } while (n /= b); 

    if (sign < 0) { 
     s[i++] = '-'; 
    } 

    s[i] = '\0'; 

    reverse(s); 
} 

int main() { 
    int base = 2, 
     input; 
    char buffer[5] = "0000"; 

    input = 127; 
    itob(input, buffer, base); 
    printf("%d in base %d is %s\n", input, base, buffer); 
    // 127 in base 2 is 1111111 

    input = 128; 
    itob(input, buffer, base); 
    printf("%d in base %d is %s\n", input, base, buffer); 
    // 0 in base 2 is 10000000 
    // Why is input now 0?! 

    return 0; 
} 

Почему значение input переменной изменяется (только тогда, когда input больше 127)? Я новичок в C, но это кажется очень неожиданным. Насколько я понимаю, аргументы функции передаются по значению.

+4

'buffer' не является достаточно большим. У вас переполнение буфера и неопределенное поведение. – user2357112

+0

Параметры функции массива настраиваются как параметры указателя. Пока указатели проходят по значению, их можно использовать для доступа к памяти вызывающего. –

+0

@ user2357112 Спасибо, что было. Если вы добавите свой комментарий в качестве ответа, я буду рад принять его. – pdoherty926

ответ

5

Ваш буфер не достаточно большой. Вы выделили места для 4-х символов и нулевой терминатор:

char buffer[5] = "0000"; 

но вы пытаетесь втиснуть 8 символов и нуль-терминатор там с itob(input, buffer, base);. Это приводит к переполнению буфера и неопределенному поведению.

3

Попробуйте использовать больший размер buffer, только с 4 символов вы не можете преобразовать число больше 127.

+1

Это не достаточно большой для 127. – user2357112