Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type of integer literals and ~ in C

Tags:

I'm a C beginner, and I'm confused by the following example found in the C answer book.

One way to find the size of unsigned long long on your system is to type:

printf("%llu", (unsigned long long) ~0);

I have no idea why this syntax works?

On my system, int are 32 bits, and long long are 64 bits.
What I expected was that, since 0 is a constant of type integer, ~0 calculates the negation of a 32-bits integer, which is then converted to an unsigned long long by the cast operator. This should give 232 - 1 as a result.

Somehow, it looks like the ~ operator already knows that it should act on 64 bits?
Does the compiler interprets this instruction as printf("%llu", ~(unsigned long long)0); ? That doesn't sound right since the cast and ~ have the same priority.

like image 507
user39967 Avatar asked Feb 16 '15 15:02

user39967


People also ask

What are the types of integer literal?

They can be represented as: Decimal integer literals. Hexadecimal integer literals. Octal integer literals.

What are literals and its types?

They could be represented in boolean, string, character, or numeric data. The literals in java are a form of data type covering the fixed values temporarily assigned fixed values as well. The literals in java are source code representing a fixed value. These literals could be assigned to any primitive variable type.


1 Answers

Somehow, it looks like the ~ operator already knows that it should act on 64 bits?

It's not the ~ operator, it's the cast. Here is how the integer conversion is done according to the standard:

6.3.1.3 Signed and unsigned integers

  • When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.
  • Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
  • Otherwise, the new type is signed and the value cannot be represented in it; either the result is implementation-defined or an implementation-defined signal is raised.

The value of signed int ~0 corresponds to -1 on systems with two's complement representation of negative values. It cannot be represented by an unsigned long long, so the first bullet point does not apply.

The second bullet point does apply: the new type is unsigned, so MAX of unsigned long long is added to -1 once to get the result into the range of unsigned long long. This has the same effect as sign-extending -1 to 64 bits.

like image 108
Sergey Kalinichenko Avatar answered Oct 05 '22 00:10

Sergey Kalinichenko