Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:如何将int转换为无符号long而不更改任何位?_C++_Casting_Bit Manipulation - Fatal编程技术网

C++ C++;:如何将int转换为无符号long而不更改任何位?

C++ C++;:如何将int转换为无符号long而不更改任何位?,c++,casting,bit-manipulation,C++,Casting,Bit Manipulation,C++:如何将int转换为无符号long而不更改任何位? 我想将值打包并解压缩到内存中。字大小为64位 此代码段说明了问题: int v1 = -2; // 0xfe unsigned long v2=(unsigned long)v1; // 0xfffe, I want 0x00fe 简单的解决办法是: unsigned long v2=(unsigned int)v1; // 0x00fe 但是,此代码位于一个模板中,其中目标类型是一个参数,因此我不得不求助于此: uint64 tar

C++:如何将int转换为无符号long而不更改任何位? 我想将值打包并解压缩到内存中。字大小为64位

此代码段说明了问题:

int v1 = -2; // 0xfe
unsigned long v2=(unsigned long)v1; // 0xfffe, I want 0x00fe
简单的解决办法是:

unsigned long v2=(unsigned int)v1; // 0x00fe
但是,此代码位于一个模板中,其中目标类型是一个参数,因此我不得不求助于此:

uint64 target = mem[index] & mask;
uint64 v;
if (value < 0) {
    switch (bits) {
    case 8:
        v = (uint8)value;
        break;
    case 16:
        v = (uint16)value;
        break;
    case 32:
        v = (uint32)value;
        break;
    }
} else {
    v = value;
}
v = v << lShift;
target |= v;
mem[index] = target;
uint64 target=mem[index]&mask;
uint64 v;
如果(值<0){
开关(位){
案例8:
v=(uint8)值;
打破
案例16:
v=(uint16)值;
打破
案例32:
v=(uint32)值;
打破
}
}否则{
v=值;
}

v=v如果你不介意输入,你会想到一个trait类:

template <typename IType> struct ToULong;

template <> struct ToULong<signed char>
{
  static inline unsigned long int get(signed char c) { return (unsigned char)(c); }
};

template <> struct ToULong<signed short int>
{
  static inline unsigned long int get(signed short int c) { return (unsigned short int)(c); }
};

/* ... signed int, signed long int, signed long long int ... */

第二次更新:如果你想更像C++,你可能应该说
静态转换(x)
,而不是
(T)(x)

要转换而不改变位,取一个引用,然后用适当的类型取消引用:

int v1 = -2; // 0xfe
unsigned long v2=*(unsigned long *)&v1;
这假设大小相同。如果sizeof(int)!=sizeof(无符号长)。您可能需要unsigned int

编辑:意识到我回答了错误的问题


Boost type_traits(我相信它是make_unsigned)可以将int类型转换为unsigned版本(如果是有符号的),如果是unsigned则什么也不做

我相信您可以使用按位AND来获得所需的结果

unsigned long v2 = 0;
v2 = v2 | v1;

假设您有C++0x支持:

#include <type_traits>
v= static_cast<std::make_unsigned<decltype(value)>::type>(value);
#包括
v=静态压力(数值);
我假设您正在对
值的类型进行参数化,否则这没有任何意义

编辑:使用
static_cast
而不是C cast,使其更像C++-ish。我想这就是为什么我投了反对票。

工会怎么样

union u1 {
    short int si;
    unsigned long int uli;

    unsigned long int stub;

    operator unsigned long int () {return uli;};
public:
    u1(short int nsi) : stub(0) {si = nsi;}

};

利用“Kerrek SB”提出的想法,我想出了一个解决方案

template <typename Tint> uint64 ToMemdata(Tint value) {
    return (uint64)value;};
template <> uint64 ToMemdata<int8>(int8 value) {
    return (uint64)((uint8)value);};
template <> uint64 ToMemdata<int16>(int16 value) {
    return (uint64)((uint16)value);};
template <> uint64 ToMemdata<int32>(int32 value) {
    return (uint64)((uint32)value);};
template <> uint64 ToMemdata<int64>(int64 value) {
    return (uint64)((uint64)value);};

template <typename Tint> void packedWrite(Tint value, int vectorIndex, uint64* pData) {

    uint64 v = ToMemdata(value);
    // This call eliminates a run time test for minus and a switch statement
    // Instead the compiler does it based on the template specialization

    uint64 aryix, itemofs;
    vectorArrayIndex(vectorIndex, &aryix, &itemofs); // get the memory index and the byte offset
    uint64 mask = vectorItemMask(itemofs); // get the mask for the particular byte
    uint64 aryData = pData[aryix]; // get the word in memory
    aryData &= mask; // mask it
    uint64 lShift = (uint64)(itemofs * sizeof(Tint) * 8); 
    uint64 d = v << lShift; // shift the value into the byte position
    aryData |= d; // put the value into memory
    pData[aryix] = aryData;
}
模板uint64 TOMEDATA(色调值){
返回(uint64)值;};
模板uint64 TOMEDATA(int8值){
返回(uint64)((uint8)值);};
模板uint64 TOMEDATA(int16值){
返回(uint64)((uint16)值);};
模板uint64 TOMEDATA(int32值){
返回(uint64)((uint32)值);};
模板uint64 TOMEDATA(int64值){
返回(uint64)((uint64)值);};
模板void packedWrite(色调值、int向量索引、uint64*pData){
uint64 v=最大数据(值);
//此调用消除了减号和switch语句的运行时测试
//相反,编译器是基于模板专门化来完成的
uint64 aryix,itemofs;
vectorArrayIndex(vectorIndex、&aryix、&itemofs);//获取内存索引和字节偏移量
uint64 mask=vectoriemmask(itemofs);//获取特定字节的掩码
uint64 aryData=pData[aryix];//在内存中获取单词
aryData&=mask;//屏蔽它
uint64 lShift=(uint64)(itemofs*sizeof(色调)*8);

uint64 d=v不应该是按位还是按位?这总是会产生0。在执行操作之前,您仍然可以升级到一个普通类型。如果我没记错的话,将
int*
转换为
unsigned long*
和取消引用是未定义的行为。对于某些编译器,int和unsigned long的大小相同,这意味着e不是未定义的行为。这与联合非常相似。@Foo-只是它打破了严格的别名规则。通过指向另一个类型的指针访问一个类型是UB@Bo是*reinterpret_cast&v1 UB?@Foo-reinterpret_cast必须是实现定义的。否则我们不知道它是什么。标准将强制转换留给我们不同的指针类型直到实现。你有64位的字大小和16位的整数?这很特别。方法签名是什么?你只提供部分信息,因此只能期望部分好的解决方案。但我怀疑你可以使用boost::type_traits来帮助。你这样做的方式是不可移植的。如果你想保留位,请t当然,您需要使用类型双关:
unsigned long v2=*(unsigned int*)&v1;
。否则,您将获得一个允许根据符号表示形式更改位的值转换。如果sizeof(int)!=sizeof(long int)那么无符号长字符的顶端可能是未定义的。@Rudy Velthuis请注意
stub
成员。这看起来很有希望,因为编译器正在执行我的示例在运行时所做的工作。因此,我将添加“v=ToULong(value);”where“IntType”,而不是短语“if(value<0)”值变量的类型。您需要调用静态成员函数,
ToULong::get(value)
——但我认为重载的自由函数也应该工作得很好,而且在概念上更简单一些。不过trait类为您提供了一些额外的类型安全性,因为自由函数也可以工作(毫无疑问)隐式可转换类型,这可能是意外的。
union u1 {
    short int si;
    unsigned long int uli;

    unsigned long int stub;

    operator unsigned long int () {return uli;};
public:
    u1(short int nsi) : stub(0) {si = nsi;}

};
template <typename Tint> uint64 ToMemdata(Tint value) {
    return (uint64)value;};
template <> uint64 ToMemdata<int8>(int8 value) {
    return (uint64)((uint8)value);};
template <> uint64 ToMemdata<int16>(int16 value) {
    return (uint64)((uint16)value);};
template <> uint64 ToMemdata<int32>(int32 value) {
    return (uint64)((uint32)value);};
template <> uint64 ToMemdata<int64>(int64 value) {
    return (uint64)((uint64)value);};

template <typename Tint> void packedWrite(Tint value, int vectorIndex, uint64* pData) {

    uint64 v = ToMemdata(value);
    // This call eliminates a run time test for minus and a switch statement
    // Instead the compiler does it based on the template specialization

    uint64 aryix, itemofs;
    vectorArrayIndex(vectorIndex, &aryix, &itemofs); // get the memory index and the byte offset
    uint64 mask = vectorItemMask(itemofs); // get the mask for the particular byte
    uint64 aryData = pData[aryix]; // get the word in memory
    aryData &= mask; // mask it
    uint64 lShift = (uint64)(itemofs * sizeof(Tint) * 8); 
    uint64 d = v << lShift; // shift the value into the byte position
    aryData |= d; // put the value into memory
    pData[aryix] = aryData;
}