Mic*_*ick 6 c++ casting bit-manipulation
C++:如何将int转换为unsigned long而不更改任何位?我想打包并将值解压缩到内存中.字大小为64位.
此代码段说明了此问题:
int v1 = -2; // 0xfe
unsigned long v2=(unsigned long)v1; // 0xfffe, I want 0x00fe
Run Code Online (Sandbox Code Playgroud)
简单的解决方案是:
unsigned long v2=(unsigned int)v1; // 0x00fe
Run Code Online (Sandbox Code Playgroud)
但是,此代码位于模板中,其中目标类型是参数,因此我不得不诉诸于此:
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;
Run Code Online (Sandbox Code Playgroud)
例如,假设"value"的类型是int(16位)和bits = 16.目标是屏蔽内存中的位值并替换它们.
有谁知道更简单的方法?
假设你有C++ 0x支持:
#include <type_traits>
v= static_cast<std::make_unsigned<decltype(value)>::type>(value);
Run Code Online (Sandbox Code Playgroud)
我假设你正在对类型进行参数化value,否则这没有任何意义.
编辑:通过使用static_cast而不是C演员,使其更多C++ - ish .我想这就是让我失宠的原因.
如果你不介意输入,我会想到一个特质类:
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 ... */
Run Code Online (Sandbox Code Playgroud)
用法:
template <typename IType>
struct Foo
{
unsigned lont int get_data() const { return ToULong<IType>::get(m_data); }
private:
IType m_data;
}
Run Code Online (Sandbox Code Playgroud)
更新:更简单,你可以做一堆重载:
unsigned long int toULong( char c) { return (unsigned char)(c); }
unsigned long int toULong(signed char c) { return (unsigned char)(c); }
unsigned long int toULong(signed short int c) { return (unsigned short int)(c); }
unsigned long int toULong(signed int c) { return (unsigned int)(c); }
unsigned long int toULong(signed long int c) { return (unsigned long int)(c); }
Run Code Online (Sandbox Code Playgroud)
第二次更新:你应该说,static_cast<T>(x)而不是(T)(x)你想要更像C++.
根据“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;
}
Run Code Online (Sandbox Code Playgroud)
使用这个概念,我能够对代码进行其他改进。例如,对 vectorItemMask() 的调用现在也已模板化。
| 归档时间: |
|
| 查看次数: |
27548 次 |
| 最近记录: |