我有一个unsigned char*
。通常这指向一大块数据,但在某些情况下,指针是数据,即。将int
值赋给unsigned char*
指针(unsigned char* intData = (unsigned char*)myInteger;
),反之亦然。将指针转换为浮点数?
但是,我需要用float
值来做到这一点,它不断给我转换错误。
unsigned char* data;
float myFloat = (float)data;
我该怎么做?
我有一个unsigned char*
。通常这指向一大块数据,但在某些情况下,指针是数据,即。将int
值赋给unsigned char*
指针(unsigned char* intData = (unsigned char*)myInteger;
),反之亦然。将指针转换为浮点数?
但是,我需要用float
值来做到这一点,它不断给我转换错误。
unsigned char* data;
float myFloat = (float)data;
我该怎么做?
如果你的编译器支持它(GCC没有),然后使用一个工会。根据C++标准,这是未定义的行为。
union {
unsigned char* p;
float f;
} pun;
pun.p = data;
float myFloat = pun.f;
这工作,如果sizeof(unsigned char *) == sizeof(float)
。如果指针大于浮点数,那么你必须重新考虑你的策略。
请参阅type punning上的维基百科文章,尤其是有关use of a union的部分。
GCC允许使用联合进行类型双击,只要您直接使用联合而不是联合类型转换... see this IBM discussion on type-pun problems了解使用GCC进行类型双击的正确和不正确的方法。
另请参阅维基百科关于strong and weak typing的文章以及关于type punning and strict aliasing的深入研究文章。
这不是一种不常见的联合使用方法,但是在C++中,这会导致两个未定义的行为:首先它访问联合的非活动成员(即,它访问的是除最后设置的成员之外的成员)。其次,如果它按预期工作,那么它会违反严格的别名,通过不相关类型(float)的glvalue访问一种类型的对象(unsigned char *)。 – bames53
不严格的别名涉及引用相同的内存位置和指向基本不同类型的指针吗?这不是这里发生的事情。看到这个SO问题http://stackoverflow.com/questions/2906365/gcc-strict-aliasing-and-casting-through-a-union。 – amdn
严格的别名规则是“如果程序试图通过以下类型之一以外的glvalue访问对象的存储值,则行为未定义:”(3.10p10)该代码正在访问存储的“ unsigned char *'对象通过'float'类型的glvalue。严格别名规则列出的任何类型均未涵盖此情况。 – bames53
unsigned char* data;
float myFloat = *(float*)data;
难道你不会忘记'&'吗?如果float数据在指针本身中是*,你应该写'&data'。 –
即使写入正确,这也是未定义的行为。 –
我敢打赌,这不是OP实际需要的 - 他们只是不知道如何提出问题 –
使用给定的变量来存储其他数据的唯一正确的方法是复制数据逐字节:
template <typename T>
void store(unsigned char * & p, T const & val)
{
static_assert(sizeof(unsigned char *) >= sizeof(T));
char const * q = reinterpret_cast<char const *>(&val);
std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&p));
}
用法:
unsigned char * p;
store(p, 1.5);
store(p, 12UL);
匹配检索功能:
template <typename T>
T load(unsigned char * const & p)
{
static_assert(sizeof(unsigned char *) >= sizeof(T));
T val;
char const * q = reinterpret_cast<char const *>(&p);
std::copy(q, q + sizeof(T), reinterpret_cast<char *>(&val));
return val;
}
用法:
auto f = load<float>(p);
我认为你的'load'声明关闭了。您不指定返回值。 –
@ RichardJ.RossIII:谢谢,修复! –
bit_cast:
template <class Dest, class Source>
inline Dest bit_cast(Source const &source) {
static_assert(sizeof(Dest)==sizeof(Source), "size of destination and source objects must be equal");
static_assert(std::is_trivially_copyable<Dest>::value, "destination type must be trivially copyable.");
static_assert(std::is_trivially_copyable<Source>::value, "source type must be trivially copyable");
Dest dest;
std::memcpy(&dest, &source, sizeof(dest));
return dest;
}
用法:
char *c = nullptr;
float f = bit_cast<float>(c);
c = bit_cast<char *>(f);
你不能,至少不容易。如果没有一些神奇的黑客攻击,这将永远不会包含有效的信息,除非输入是正确的IEEE格式。 –
@ RichardJ.RossIII,除非你知道我不知道的东西(这不是不太可能,考虑到这是C++),你可以很容易地做到这一点。 –
在您的平台上,sizeof(unsigned char *)是否等于sizeof(float)?如果不是的话,那么你究竟期待做什么呢? (不要介意一般行为的可怕的不确定性...) – Nemo