3

In the following code, the scanf() in main() turns one of the input numbers from a non-zero number into zero, as shown by a debugging printf() in the while loop. I've tested it on several compilers but only to keep getting the same result. Please help me out by telling me why this is such. Thank you.

 #include <stdio.h>

unsigned srl (unsigned x, int k)
{
    /* perform shift arithmetically */
    printf("x = %u, (int) x= %d\n", x, (int) x);
    unsigned xsra = (int) x >> k;
    printf("\nxsra before was: %u\n", xsra);
    unsigned test = 0xffffffff;
    test <<= ((sizeof (int) << 3) - k); // get e.g., 0xfff00...
    printf("test after shift is: %x, xsra & test = %x\n", test, xsra & test);
    if (xsra & test == 0) // if xsrl is positve
        return xsra;
    else
        xsra ^= test;    // turn 1s into 0s

    return xsra;
}

int sra (int x, int k) 
{
    /* perform shift logically */
    int xsrl = (unsigned) x >> k;
    unsigned test = 0xffffffff;
    test << ((sizeof (int) << 3) - k + 1); // get e.g., 0xffff00...
    if (xsrl & test == 0) // if xsrl is positve
        return xsrl;
    else 
                            xsrl |= test;

        return xsrl;
}

int main(void)
{
    int a;
    unsigned b;
    unsigned short n;

    puts("Enter an integer and a positive integer (q or negative second number to quit): ");
    while(scanf("%d%u", &a, &b) == 2 && b > 0)
    {
        printf("Enter the number of shifts (between 0 and %d): ", (sizeof (int) << 3) - 1);
        scanf("%d", &n);
        if (n < 0 || n >= ((sizeof (int)) << 3))
        {
            printf("The number of shifts should be between 0 and %d.\n", ((sizeof (int)) << 3) - 1);
            break;
        }
        printf("\nBefore shifting, int a = %d, unsigned b = %u\n", a, b);
        a = sra(a, n);
        b = srl(b, n);
        printf("\nAfter shifting, int a = %d, unsigned b = %u\n", a, b);
        puts("\nEnter an integer and a positive integer (q or negative second number to quit): ");
    }
    puts("Done!");

    return 0;
}
4
  • 2
    Specifier for unsgined short should be %hu and not %u. Commented Aug 27, 2016 at 4:05
  • It would have been easier if you let me know which one was becoming 0 so I didn't have to compile the whole thing myself... (Well actually, I could figure it it was probably n after reloading and seeing amey's comment.) Also, OP, n can never be negative as it's unsigned. Commented Aug 27, 2016 at 4:10
  • 1
    He's actually using %d, not %u, for n, albeit still incorrect. Commented Aug 27, 2016 at 4:26
  • Thank you, ameyCU and RastaJedi. Your comments are very to-the-point and very helpful. This is a typical overflow, indeed. Commented Aug 28, 2016 at 12:31

1 Answer 1

4

The problem is that n is an unsigned short, which has less size than a normal int. When you call scanf("%d", &n);, it reads the value into n and potentially overwrite the existing b value if b has the memory location right after n.

All you have to do is to change that problematic line into:

scanf("%hu", &n);

the h is a modifier for unsigned short int, from here.

Sign up to request clarification or add additional context in comments.

3 Comments

This is another example of why you should always compile with -Wall and -Wextra.
Thank you, lyang. Your answer is very helpful. That's true, there's an overflow because of the incorrect input format specifier.
Thank you again, RastaJedi. I had assumed that the -Wall and -Wextra options are defaults but it is actually not default with every compiler

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.