Jyoti Rawat
Jyoti Rawat

Reputation: 21

DataTypes and format specifier

Why the value of the input variable is set to zero if I pass incorrectly ordered type specifier for id variable?

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 100
int main()
{
    int i=0;
    int input;
    char *name=(char *)malloc(sizeof(char)*MAX);
    unsigned short int id;

    printf("\nPlease enter input:\t");
    scanf("%d", &input);
    getchar();//to take \n

    printf("\nEnter name.....\n");
    fgets(name,MAX,stdin);

    printf("\nEnter id: ");
    scanf("%uh",&id);//type specifier should have been %hu
    printf("%d",input);//value set to 0?
}

Why is input being overridden by scanf("%uh", &id) ?

Upvotes: 0

Views: 215

Answers (3)

Adrian Mole
Adrian Mole

Reputation: 51815

EDIT (After re-reading question/comments):

Mentat has nailed the problem! I'll leave some fragments of my original answer, with some additions ...

(1) The warning about using %uh should be accepted at face value: to input a short integer (signed or unsigned), you need the h modifier before the type specifier (u or d) - that's just the way scanf format specifiers work.

(2) Your code happens to work on MSVC, so I missed the point. With clang-cl I found your error: As the h size modifier is being ignored, the value read in by '%uh' is a (long or 32-bit) unsigned, which is being written to memory that you've allocated as a short (16-bit) unsigned. As it happens, that variable (id)is in memory next to input, so part of input is being overwritten by the high 16-bits of the 32-bit unsigned you are writing to id.

(3) Try entering a value of 65537 for your first input and then the value will still be modified (probably to 65536), but not cleared to zero.

(4) Recommend: Accept and upvote the answer from Mentat. Feel free to downvote my answer!

Yours, humbly!

Upvotes: 0

Mentat
Mentat

Reputation: 381

Jyoti Rawat

You have what I call a memory over run error. Microsoft (Visual Studio) calls it:

"Stack around the variable ‘id’ was corrupted"

Not all computer systems treat memory over runs errors the same. Visual Studio/Windows catch this error and throw an exception.

enter image description here

OpenVMS would just execute the instruction and then continue on to the next instruction. In either case, if the program continues, its behavior will be undefined.

In English, you are writing more bits of data into a variable that cannot contain it. The extra bits are written to other memory locations not assigned to the variable. As mention by chux, statements that follow will have undefined behavior.

Solution:

As you already know and mention by others, change the format specifier from "uh" to "hu".

Things to note about your code:

  • As stated my Adrian, using "hu" as a format specifier will work. This specifier expects a pointer to a unsigned short int variable. Click here to go to scanf format specifiers wiki page.
  • When you specify “%uh”, scanf pares out the %u as the format specifier and treats the rest ('h') as text to be ignored.
  • The format specifier 'u' expects a pointer to an unsigned int variable (unsigned int *).
  • The format specifier 'hu' expects a pointer to an unsigned short variable (unsigned short int *).

Upvotes: 2

chux
chux

Reputation: 153338

Why the value of the input variable is set to zero if I pass incorrectly ordered type specifier to id variable?

unsigned short int id;
scanf("%uh",&id);//type specifier should have been %hu

scanf() first uses "%u" and looks for a matching unsigned * argument. As code passed a unsigned short * the result is undefined behavior (UB).

The result of 0 is not demo'd with printf("%d",input);. Perhaps OP meant printf("%d",id);?

In any case, code after the UB of scanf() is irrelevant. It might print 0 today or crash the code tomorrow - it is UB.

Upvotes: 0

Related Questions