Rohit Jain
Rohit Jain

Reputation: 831

K&R chapter 2: Difference between u and l integer suffix in C

I am a student, going through the book by Kerningham and Ritchie for C.

A line in the book says that -1l is less than 1u because in that case unsigned int is promoted to signed long. But -1l > 1ul because in this case -1l is promoted to unsigned long.

I can't really understand the promotion properly. What will be the value of -1l when it is promoted to unsigned long? It'll be great if anyone can help. Thanks.

Upvotes: 4

Views: 419

Answers (4)

rubenvb
rubenvb

Reputation: 76785

In -1l > 1ul the -1l is promoted to unsigned long, and by definition and Standard, -1 cast to an unsigned type will be the largets value representable by that unsigned type.

I got my inspiration from memory of this answer here to a quite relevant question.

And after looking at the C99 draft I have lingering around, see for example 6.3.1.3(2), where it says the maximum value representable by the type will be added or subtracted from the original value until it fits in the new type. I must warn you that char, although it is an integer type, is treated special: it is implementation defined if char is signed or unsigned. But that is, strictly, beside the question at hand.

Upvotes: 2

ninjalj
ninjalj

Reputation: 43748

This is actually a conversion. Promotions go from types with less rank than an integer to integer.

The rules for integer conversions in C are somewhat complex. They are, as per ISO C99 §6.3.1.8 ¶1:

Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:

If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

Otherwise, 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, then the operand with unsigned integer type is converted to the type of the operand with signed integer type.

Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type.

I'll try to explain them:

Try to convert to the larger type. When there is conflict between signed and unsigned, if the larger (including the case where the two types have the same rank) type is unsigned, go with unsigned. Otherwise, go with signed only in the case it can represent all the values of both types.

Upvotes: 1

unpythonic
unpythonic

Reputation: 4070

When you're learning C, if you have a question, just write yourself a simple program:

#include <stdio.h>
main() {
  int si = -1;
  unsigned int ui = 1;
  if ( si > ui ) printf("-1l > 1u\n");
  else           printf("-1l <= 1u\n");
}

You'll see that -1l > 1u is shown for the output.

Because both si and ui have the same rank (they're both ints), the rule says that the negative value will be promoted to unsigned at set to UINT_MAX which is the largest possible unsigned value.

Upvotes: 0

Lundin
Lundin

Reputation: 215115

Implicit promotions are one of the most difficult things in the C language. If you have a C code expression looking like

if(-1l > 1ul)

then no "integer promotions" take place. Both types are of the same size, but different signedness. -1l will then be converted to unsigned long with a very large value. This is one of the rules in the "usual arithmetic conversions".

Upvotes: 1

Related Questions