Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you specify a 64 bit unsigned int const 0x8000000000000000 in VS2008?

Tags:

I read about the Microsoft specific suffix "i64" for integer constants. I want to do an UNsigned shift to a ULONGLONG.
ULONGLONG bigNum64 = 0x800000000000000i64 >> myval;

In normal C, I would use the suffix "U", e.g. the similar 32 bit operation would be
ULONG bigNum32 = 0x80000000U >> myval;

I do NOT want the 2's complement sign extension to propogate through the high bits. I want an UNSIGNED shift on a 64 bit const number. I think my first statement is going to do a SIGNED shift right.

I tried 0x800000000000000i64U and 0x800000000000000u64 but got compiler errors.

like image 646
franji1 Avatar asked May 14 '10 16:05

franji1


People also ask

What is 64-bit unsigned integer?

uint64. A 64-bit unsigned integer. It has a minimum value of 0 and a maximum value of (2^64)-1 (inclusive).

How do you create a 64-bit integer?

You can declare 8-, 16-, 32-, or 64-bit integer variables by using the __intN type specifier, where N is 8, 16, 32, or 64. The types __int8 , __int16 , and __int32 are synonyms for the ANSI types that have the same size, and are useful for writing portable code that behaves identically across multiple platforms.

What is the 64-bit integer limit?

As a recap, remember that the maximum number stored in a 64 bit register / variable is 2^64 – 1 = 18446744073709551615 (a 20 digit number).

Is Int64 to signed or unsigned?

2. Int64 stands for signed integer. UInt64 stands for unsigned integer.


2 Answers

You can use the suffix ull, which is the standard (C99 and C++0x) way to specify an unsigned long long integer literal, and a long long is at least 64 bits.

like image 79
James McNellis Avatar answered Sep 29 '22 19:09

James McNellis


Funny enough, but you don't actually need to add any suffix to your hex constant in order for it to be treated correctly. Section 6.4.4.1 of the C standard and section 2.14.3 of the C++ standard contain the following table:

Suffix       | Decimal Constant       | Octal or Hexadecimal Constant -------------+------------------------+------------------------------ none         | int                    | int              | long int               | unsigned int              | long long int          | long int              |                        | unsigned long int              |                        | long long int              |                        | unsigned long long int -------------+------------------------+------------------------------ u or U       | unsigned int           | unsigned int              | unsigned long int      | unsigned long int              | unsigned long long int | unsigned long long int -------------+------------------------+------------------------------ l or L       | long int               | long int              | long long int          | unsigned long int              |                        | long long int              |                        | unsigned long long int -------------+------------------------+------------------------------ Both u or U  | unsigned long int      | unsigned long int and l or L   | unsigned long long int | unsigned long long int -------------+------------------------+------------------------------ ll or LL     | long long int          | long long int              |                        | unsigned long long int -------------+------------------------+------------------------------ Both u or U  | unsigned long long int | unsigned long long int and ll or LL |                        | 

This table tells us what type an integer constant will have. The integer constant's type will be the first type in which it the value fits.

This means that the compiler will iterate through the following types for the hexadecimal constant 0x800000000000000 (it has no suffix, so it uses the "none" row, and it's a hex constant, so it uses the "Hexadecimal Constant" column), and it will use the first type which can store that value*:

  1. int: No, a 32-bit signed integer can't store this value.
  2. unsigned int: No, a 32-bit unsigned integer can't store this value.
  3. long int: No, a 32-bit signed integer can't store this value.
  4. unsigned long int: No, a 32-bit unsigned integer can't store this value.
  5. long long int: No, a 64-bit signed integer can't store this value.
  6. unsigned long long int: Yes, a 64-bit unsigned integer can store this value. Since this is the first type that can fully store the value, this is the type that the integer constant will have.

So, to answer your question of "How can I write and use the value 0x800000000000000 and make sure the compiler won't treat the high bit as a sign bit?": Simply just write unsigned long long value = 0x800000000000000.

If you want to do some bitwise arithmetic with the value, you can just go ahead and do that (i.e. just write 0x800000000000000 >> myval). You're guaranteed that it will not be treated as an overflowed signed integer, and your right shift won't do any sign extension because it's a positive value.

*I'm assuming that int is 32-bits, long is 32-bits, and long long is 64-bits. Note that your compiler might use different bit sizes for these types, which may change the end result (though the process will still be the same).

like image 22
Cornstalks Avatar answered Sep 29 '22 18:09

Cornstalks