2010-05-14 31 views
19

我读了整数常量的Microsoft特定后缀“i64”。我想做一个UNSIGN的转变成ULONGLONG。
ULONGLONG bigNum64 = 0x800000000000000i64 >> myval;如何在VS2008中指定一个64位的unsigned int const 0x8000000000000000?

在正常的C中,我会使用后缀“U”,例如,类似的32位操作将是
ULONG bigNum32 = 0x80000000U >> myval;

我不希望2的补码符号扩展传播高位。我想要一个64位常数的UNSIGNED移位。我认为我的第一个声明是要做一个正确的转变。

我试过0x800000000000000i64U0x800000000000000u64但有编译器错误。

+2

在我的Visual Studio中,limits.h具有语法0xffffffffffffffffui64,因此0x800000000000000ui64应该可以工作。但是,这是一个较新的版本,所以也许它在Visual Studio 2008中不起作用。 – anatolyg 2015-07-21 10:19:03

+1

对于十六进制整数,@MM:U可以是unsigned int,unsigned long int或unsigned long long int不变。 UL可以是'unsigned long int'或'unsigned long long int'。参见C标准的6.4.4.1(或C++标准的2.14.3)。鉴于此,我不认为OP的例子不正确或需要修改。 – Cornstalks 2016-03-23 00:01:59

+0

这是一个较老的问题。在C++ 11中,我认为不需要任何后缀。只有一个无符号的64位整型可以保存该常量。无符号long long必须至少为64位,并且这是编译器应该尝试以十六进制格式的文本类型的列表。 http://en.cppreference.com/w/cpp/language/integer_literal – 2016-03-23 17:24:08

回答

29

可以使用后缀ull这是标准(C99和C++ 0x)方式来指定unsigned long long整数文字,并且long long至少为64位。

+0

这工作!谢谢! – franji1 2010-05-14 16:22:21

+0

**编译器警告**''-Wlong-long'可以在编译器命令行或'#pragma GCC诊断忽略'-Wlong-long''的代码中禁用。 [这里是一个很好的例子](http://stackoverflow.com/a/16062548/673991)暂时为一段代码做这件事。 – 2014-06-20 13:31:12

+0

@ BobStein-VisiBone:如果您使用C99模式或更高版本进行编译,您将不会收到任何有关“long long”的警告。 – AnT 2016-03-23 14:46:19

0

这里有一个办法:

int main() 
{ 
    uint64_t val1=0x1p63; //1 * 2**63 
    uint64_t val2=((uint64_t)0x1p63)-1; //0x1p63 is a float constant 
    uint64_t val3= ((uint64_t)0x1p63) >> 2; 
    cout << hex << "val1=" << val1 << " val2=" << val2 << " val3=" << val3 << endl; 
    return 0; 
} 

VAL1 = 80000000亿VAL2 = 7fffffffffffffff VAL3 = 20000000亿

5

滑稽足够了,但你实际上并不需要任何后缀添加到您的十六进制常量,以便它被正确处理。 C标准和C++标准的第2.14.3第6.4.4.1包含下表:

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 |      | 

此表告诉我们一个整型常量会产生什么样的类型。整数常量的类型将是它适合的第一个类型。

这意味着编译器将遍历以下类型的十六进制常量0x800000000000000(它没有后缀,所以它使用“none”行,它是一个十六进制常量,因此它使用“十六进制常量”列),它会使用能够存储值*第一种类型:

  1. int:没有,一个32位带符号整数不能存储此值。
  2. unsigned int:不,一个32位无符号整数不能存储这个值。
  3. long int:不,32位有符号整数不能存储此值。
  4. unsigned long int:不,32位无符号整数不能存储此值。
  5. long long int:否,64位有符号整数不能存储此值。
  6. unsigned long long int,一个64位无符号整数可以存储此值。由于这是第一种可以完全存储该值的类型,因此这是整型常量将具有的类型。

因此,要回答你的问题“我如何编写和使用的价值0x800000000000000并确保编译器将不能治疗高位为符号位?”:简单地只写unsigned long long value = 0x800000000000000

如果您想对值进行一些按位运算,您可以继续前进并执行该操作(即只写0x800000000000000 >> myval)。您可以保证它不会被视为溢出的有符号整数,并且您的右移不会执行任何符号扩展,因为它是正值。

*我假设int是32位,long是32位,并且是long long 64比特。请注意,您的编译器可能会为这些类型使用不同的位大小,这可能会改变最终结果(尽管过程仍然相同)。

+0

你需要小心,虽然。如果你想声明一个没有后缀的无符号long long,那么你会遇到麻烦:考虑'printf(“%lx \ n”,(0x40000000 <<1)>> 1);'左/右移应该返回0x40000000,但如果你运行这个,你会得到0xc0000000。 – 2016-07-26 00:28:10

相关问题