Naman Vyas
Naman Vyas

Reputation: 99

Using %d with char , unexpected results

Text editor : VS code

Compiler : minGW

I was needed to store a number between 1-10, so I thought why don't store it in a char variable because it takes only 1 byte.

so, look at the following code

char a = 3;
printf("%d", a);

OUTPUT

3

it worked fine

Then I decided to take value as input using scanf

Here's the code for that

char a;
printf("Enter number : ");
scanf("%d", &a);
printf("You entered : %d", a);

OUTPUT

Enter number : 9
You entered : 9

It worked fine too, but problem lies when I tried with two variables

Look at the the code below

char a = 2, b = 3;

printf("before scanf a : %d\n", a);
printf("before scanf b : %d\n", b);

printf("Enter new value of a : ");
scanf("%d", &a);

printf("after scanf a : %d\n", a);
printf("after scanf b : %d\n", b);

OUTPUT

before scanf a : 2
before scanf b : 3     
Enter new value of a : 9
after scanf a : 9
after scanf b : 0 //Notice value of b has changed to 0

Even though, I didn't even touched b's value. still it changed. . I tried a lot to figure it out but failed, I'm a beginner. I think it's something to do with stdin/out stream. please help me here..

Upvotes: 0

Views: 687

Answers (3)

th33lf
th33lf

Reputation: 2275

The format specifier %d specifies int, not char. When you use this format specifier with printf and pass a char, this doesn't really matter because char gets implicitly promoted to an int.

But with scanf, you end up passing a char pointer (note that scanf uses &a instead of simply a) where scanf expects an int pointer. Hence scanf ends up copying an int into a char, which means that data spills over into the adjacent memory location(s). In your case, this adjacent location happens to be the variable b, thus the value of b gets overwritten with the MSB of the integer that is input, which in this case is 0.

PS: I should also mention the fact that you shouldn't really rely on this behaviour. What I mentioned above is the most likely explanation for your observation. This particular scenario falls under undefined behaviour so a different compiler, different hardware or a different run of the same program could theoretically have resulted in a drastically different outcome and it would still be perfectly legal! The proper solution is to use an int instead of a character. On a modern machine, you are not saving much anyway with these antics.

Upvotes: 1

uncoder21
uncoder21

Reputation: 11

What's happening is that your program thinks a is of type int. Since the size of an int is 4 bytes, if you do:

char a = 2, b = 3, c = 4, d = 5, e = 6;

scanf("%d", &a) will corrupt the values of b, c, d (but will not corrupt the value of e, because e is the 5th byte, and the size of int is 4), because scanf thinks that you've passed a pointer to an int, not to a char.

Upvotes: 0

Eric Postpischil
Eric Postpischil

Reputation: 222302

scanf("%d", &a); instructs scanf to read a decimal numeral and assign it to an int pointed to by &a. Since &a points to a char, not an int, the behavior is not defined by the C standard.

Proper code is to declare a as a signed char and use scanf("%hhd", &a);. (Technically, there is no conversion specifier to assign to a char.)

Upvotes: 1

Related Questions