Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

have I coded this incorrectly?

Tags:

c

gcc

I did some C programming couple decades ago. I am trying to re-learn the language. I wrote this. I get something unexpected. When I change the 'short int' to 'int', it seems to work. Can anyone look at my code to see if anything is wrong with it or is this a compiler issue. I am using gcc on Linux.

#include <stdio.h>

int main(void) {

    short int age = 0;
    short int num_1_yr_olds = 0;
    short int num_2_and_3_yr_olds = 0;
    short int num_above_3_yr_olds = 0;

    while(1) {

        printf ("Enter age: ");
        scanf ("%d", &age);

        if (age < 1) {
            break;
        }

        switch (age) {
            case 1:
                ++num_1_yr_olds;
                break;
            case 2:
            case 3:
                ++num_2_and_3_yr_olds;
                break;
            default:
                ++num_above_3_yr_olds;
                break;
        }
    }
    printf ("Number of 1 year olds = %d\n", num_1_yr_olds);
    printf ("Number of 2 and 3  year olds = %d\n", num_2_and_3_yr_olds);
    printf ("Number above 3 year olds = %d\n", num_above_3_yr_olds);
}

Input

Enter age: 1
Enter age: 1
Enter age: 1
Enter age: -1

Output

Number of 1 year olds = -1
Number of 2 and 3  year olds = 0
Number above 3 year olds = 0

num_1_yr_olds value is getting messed up. I expected a 3, I get a -1. The value of num_1_yr_olds becomes a -1 regardless of input.

like image 515
rpat Avatar asked Dec 01 '25 15:12

rpat


2 Answers

Your problem lies here:

short int age = 0;
:
scanf ("%d", &age);

You really need to ensure that your data types match your format string. The correct format specifier for a short int is %hd, not %d.

Some compilers will actually check this and warn you.

What's likely to be happening is that the misalignment of data and format string is causing the short int to become the "wrong" value hence the counts are being screwed up.


In more depth, for a two's complement, little-endian architecture like x86, scanning an int into a short may put the least significant half into age and the most significant half into num_1_year_olds (if it's adjacent to age in memory).

Graphically, it may be clearer to think of it like this:

                         shorts in memory
                     +-----------------------+
What scanf("%hd") =< |          age          | \
  will write to.     +-----------------------+  = What scanf("%d")
                     |    num_1_year_olds    | /    will write to.
                     +-----------------------+
                     | num_2_and_3_year_olds |
                     +-----------------------+
                     | num_above_3_year_olds |
                     +-----------------------+

So, when you enter 1, age becomes 1 and num_1_year_olds becomes 0.

Each time you do that, it increases num_1_year_olds because age is 1 but that will be overwritten by the scanf the next time you get input.

When you finally enter -1 (all 1 bits in two's complement), age becomes -1 and so does num_1_year_olds.

Then, because age is less than one, the loop breaks, and the values are what you see: {-1, 0, 0}.

like image 150
paxdiablo Avatar answered Dec 03 '25 11:12

paxdiablo


Try

scanf ("%hd", &age);

Since age is of type short int.

like image 39
Hernan Velasquez Avatar answered Dec 03 '25 10:12

Hernan Velasquez



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!