160

I have the following program

#include <stdio.h>

int main(void)
{
    unsigned short int length = 10; 

    printf("Enter length : ");
    scanf("%u", &length);

    printf("value is %u \n", length);

    return 0;
}

Which when compiled using gcc filename.c issued the following warning (in the scanf() line).

warning: format ‘%u’ expects argument of type ‘unsigned int *’, but argument 2 has type ‘short unsigned int *’ [-Wformat]

I then referred the C99 specification - 7.19.6 Formatted input/output functions and couldn't understand the correct format specifier when using the length modifiers (like short, long, etc) with unsigned for int data type.

Is %u the correct specifier unsigned short int? If so why am I getting the above mentioned warning?!

EDIT: Most of the time, I was trying %uh and it was still giving the warning.

Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98

5 Answers5

194

Try using the "%h" modifier:

scanf("%hu", &length);
        ^

ISO/IEC 9899:201x - 7.21.6.1-7

Specifies that a following d , i , o , u , x , X , or n conversion specifier applies to an argument with type pointer to short or unsigned short.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
62

For scanf, you need to use %hu since you're passing a pointer to an unsigned short. For printf, it's impossible to pass an unsigned short due to default promotions (it will be promoted to int or unsigned int depending on whether int has at least as many value bits as unsigned short or not) so %d or %u is fine. You're free to use %hu if you prefer, though.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
11

From the Linux manual page:

h      A  following  integer conversion corresponds to a short int or unsigned short int argument, or a fol‐
       lowing n conversion corresponds to a pointer to a short int argument.

So to print an unsigned short integer, the format string should be "%hu".

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    I don't think that's how you "printf" short ints because they are automatically promoted to ints (just like chars). – Alexey Frunze Jan 02 '12 at 11:00
  • 3
    @Alex %hu/%hd in printf does work. It was %hhu/%hhd that is only available starting with C99. %h and %hh imply a &0xFFFF resp. &0xFF on the passed integer. – jørgensen Jan 02 '12 at 13:11
8

Here is a good table for printf specifiers. So it should be %hu for unsigned short int.

And link to Wikipedia "C data types" too.

FooBar167
  • 2,721
  • 1
  • 26
  • 37
0

For printf, it's impossible to pass an unsigned short due to default promotions (it will be promoted to int or unsigned int depending on whether int has at least as many value bits as unsigned short or not) so %d or %u is fine.

But still he can manually convert value of this short int to a char array of '0' and '1' and then use another loop to create a short int value and print it I guess.

Let us do it this way:

struct byte3data {
    char a;
    char b;
    char c;
};
void my_printf(byte3data myOwnType) {
    // Writing 3 bytes with printf() in the way we want
}

printf is just basic tool, and this this how it should be treated I think. You can manage bits in any way you want. And with floating point arithmetic You can say yes or no but also how much. Try to change printf to printfs in your sentence and think about it again.

user16217248
  • 3,119
  • 19
  • 19
  • 37
  • Ok ok ok, don't be angry, I', correcting my answer. –  Apr 15 '23 at 04:24
  • I am not angry, I am just having trouble understanding how your answer solves the problem. Are you suggesting to create your own version of `printf()`? – user16217248 Apr 15 '23 at 04:52
  • 1
    Yes and no, what I mean is "printf" can be "printfs" - You can use them to write any data, or by using char data type - or(if You need smaller bit representaion - smaller then 8 bits, operate on diffirent areas). I wrote my first answer when I was making application to convert any data type to any data type, so looked deeper in practical way on the subject. –  Apr 15 '23 at 06:57