Search code examples
cgccmingw32

int variable changes to 1 after 'while' loop


I was trying to make a 'decimal to binary' program. It should convert from 0 to 255 only and it does.

I have two variables, 'n' and 'temp', when the user first enters the number I store it on 'n'. Then I assign 'n' to 'temp' (thus creating a copy, at least that's what I think I'm doing).

then I only use 'temp' in my code. I never use 'n', not until the end where I decide to print the number the user entered. And here comes the problem, if I enter a number greater than 255, the variable 'n' changes to 1.

I tried running my code through a couple C online compilers and all of them output the variable 'n' the right way, meaning that despite the binary not working when the numbers is greater than 255 (as intended) they print the entered value.

I found one online compiler where it doesn't print the 'n' variable if its greater than 255.

https://www.tutorialspoint.com/compile_c_online.php

If you run my code through this compiler, you'll see how the variable 'n' changes to 1 without it being used.

I know the 'binary part' won't work if you use a number greater than 255. I want to know why 'n' changes out of nowhere.

#include <stdio.h>

int main()
{
    int bin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
    int arrSize = 7;
    int n;
    int temp;

    scanf("%d", &n);

    temp = n;

    while(temp != 0)
    {
        bin[arrSize] = temp % 2;

        temp = temp / 2;
        arrSize = arrSize - 1;
    }

    printf(" Decimal: %d ----> binary: ", n);
    for(int i = 0; i <= 7; i++)
    {
        printf("%d", bin[i]);
    }
    printf("\n");


    return 0;
}

Solution

  • You've run through a "Buffer overflow". A quick definition for that:

    A buffer overflow occurs when a program or process attempts to write more data to a fixed length block of memory, or buffer, than the buffer is allocated to hold. Since buffers are created to contain a defined amount of data, the extra data can overwrite data values in memory addresses adjacent to the destination buffer unless the program includes sufficient bounds checking to flag or discard data when too much is sent to a memory buffer.

    The error in your code remains in this while loop:

    while(temp != 0){
       //I added this line to make it clear
       printf("inside loop\tarrSize=%d\n",arrSize);
       bin[arrSize] = temp % 2;
       temp = temp / 2;
       arrSize = arrSize - 1;
    }
    

    For an input equals to 300 (The error will occur for each input > 255) you'll have this output:

    inside loop arrSize=7
    inside loop arrSize=6
    inside loop arrSize=5
    inside loop arrSize=4
    inside loop arrSize=3
    inside loop arrSize=2
    inside loop arrSize=1
    inside loop arrSize=0
    inside loop arrSize=-1
    inside loop arrSize=0
    

    The problem is that we have an index equals to -1, You'll ask what will happen ? well in fact arrays are pointers to the address of the first element of the table + the offset (index * size of the type of the table) which means that for bin[-1] it is in fact arrSize, and bin[-2] is in fact n. You can check this by verifying the addresses as it follows:

    printf("@ of bin[-1]:\t%p\n",(void*)&bin[-1]);
    printf("@ of arrSize:\t%p\n\n",(void*)&arrSize);
    printf("@ of bin[-2]:\t%p\n",(void*)&bin[-2]);
    printf("@ of n:\t\t\t%p\n",(void*)&n);
    

    which with my compiler gave me:

    @ of bin[-1]:   0x7ffe00e32f9c
    @ of arrSize:   0x7ffe00e32f9c
    
    @ of bin[-2]:   0x7ffe00e32f98
    @ of n:         0x7ffe00e32f98
    

    So you changes without knowing bin[-1] (or bin[-2] according to the value of n) which is in fact arrSize (or n)..

    How you can fix this ? I advice you to verify the index every time you want to loop over an array (the condition of the loop must be in function of arrSize). Or you can if you want for this specific exemple to ignore that and focus on the logic: verify the input (in your case the input n must be: 0 <= n <= 255)