0

I was playing around with data types and format specifiers. Compiling the first snippet of code gives no errors but when I try to use unsigned shorts (or shorts in general) I get an error on line 12: printf("n - 2 = %hu\n", n-2); Why so?

#include <stdio.h>

int main()
{
    unsigned int n;

    scanf("%u", &n);

    printf("unsigned int is: %u\n", n);

    printf("n - 2 = %u\n", n-2);

    return 0;
}


#include <stdio.h>

int main()
{
    unsigned short n;

    scanf("%hu", &n);

    printf("unsigned short is: %hu\n", n);

    printf("n - 2 = %hu\n", n-2); //12:29: error: format specifies type 'unsigned short' but the argument has type 'int'

    return 0;
}

2 Answers 2

1

INT02-C. Understand integer conversion rules

Conversions can occur explicitly as the result of a cast or implicitly as required by an operation. Although conversions are generally required for the correct execution of a program, they can also lead to lost or misinterpreted data. Conversion of an operand value to a compatible type causes no change to the value or the representation. The C integer conversion rules define how C compilers handle conversions. These rules include integer promotions, integer conversion rank, and the usual arithmetic conversions. The intent of the rules is to ensure that the conversions result in the same numerical values and that these values minimize surprises in the rest of the computation. Prestandard C usually preferred to preserve signedness of the type.

Usual Arithmetic Conversions

The usual arithmetic conversions are rules that provide a mechanism to yield a common type when both operands of a binary operator are balanced to a common type or the second and third operands of the conditional operator ( ? : ) are balanced to a common type. Conversions involve two operands of different types, and one or both operands may be converted. Many operators that accept arithmetic operands perform conversions using the usual arithmetic conversions. After integer promotions are performed on both operands, the following rules are applied to the promoted operands:

  1. If both operands have the same type, no further conversion is needed.
  2. If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.
  3. If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type.
  4. If the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type.
  5. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

https://www.securecoding.cert.org/confluence/display/c/INT02-C.+Understand+integer+conversion+rules

Your code would work if you cast the result to (unsigned short), like this:

printf("n - 2 = %hu\n", (unsigned short)(n - 2));

EDIT: I'll leave this answer here for informative purposes, but you can ignore it. I hadn't seen that DinoCoderSaurus had already answered.

1
  • Thank you very much Yuri.
    – Alberto
    Commented Oct 25, 2016 at 21:29
1

Looks like C is (internally) casting the constant 2 (or probably more correctly, the result of n - 2) as an int since that is the essential difference between the two printfs.

You might search the internet-at-large for "C integer promotion rules". There are a lot of hits on the subject. This might be an interesting place to start.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .