我正在尝试将字符流转换为float *,但是不知何故无法获得正确的结果。
char *char_data_ = static_cast<char *>("abcdefghijklmnopqrstuvwx");
float *float_data_ = reinterpret_cast<float *>(malloc(strlen(char_data_)/sizeof(float)));
printf("%ld\n", strlen(char_data_));
memcpy(float_data_, reinterpret_cast<float *>(char_data_), strlen(char_data_)/sizeof(float));
for ( auto n = 0 ; n < strlen(char_data_)/sizeof(float); n++) {
printf("%f\n", *(float_data_ + n));
}
以下是我的结果,但其清除是错误的。有人可以看看吗?
16777999408082104352768.000000
0.000000
0.000000
0.000000
0.000000
0.000000
是否可以使用联合来解决此问题?
我希望每个字符流都有4个字节的块,并将其保存到浮点数组中。
答案 0 :(得分:0)
如何使用union或memcpy将char *转换为float *?
使用memcpy和reinterpretcast:
#include <cstdio>
#include <string>
#include <cstring>
#include <cassert>
#include <cstddef>
void using_pointer(const char *s, size_t slen) {
const float *f = reinterpret_cast<const float*>(s);
for (size_t i = 0; i < slen/sizeof(float); ++i) {
printf("%zu = %f\n", i, f[i]);
}
}
void using_memcpy(const char* s, size_t slen) {
float* f = new float[slen/sizeof(float)];
memcpy(f, s, slen/sizeof(float)*sizeof(float));
for (size_t i = 0; i < slen/sizeof(float); ++i) {
printf("%zu = %f\n", i, f[i]);
}
delete f;
}
int main() {
static_assert(sizeof(float) == 4, "");
std::string stdstr(
"\x00\x00\x80\x3f" // float 1.0
"\x00\x00\x81\x3f" // just randomly changed 0x80 to 0x81
"\x00\x00\x82\x3f"
, 4 * 3);
printf("using_pointer:\n");
using_pointer(stdstr.c_str(), stdstr.size());
printf("using_memcpy:\n");
using_memcpy(stdstr.c_str(), stdstr.size());
std::string s2("abcdefghijklmnopqrstuvwx");
printf("Last:\n");
using_memcpy(s2.c_str(), s2.size());
return 0;
}
将在http://www.onlinegdb.com使用的计算机上输出:
using_pointer:
0 = 1.000000
1 = 1.007812
2 = 1.015625
using_memcpy:
0 = 1.000000
1 = 1.007812
2 = 1.015625
Last:
0 = 16777999408082104352768.000000
1 = 4371022013021616997400576.000000
2 = 1138400301458999111806091264.000000
3 = 296401655701622853703074578432.000000
4 = 77151445562813935304650187079680.000000
5 = 20076561220099179535696200212676608.000000
@edit:正如@drescherjm在评论中指出的那样,除非基于未定义的行为,否则在C ++中不可能使用并集在char和float表示形式之间进行转换。在C ++中,并集不用于更改字节的表示形式。联合用于最多存储多个对象之一。您可以一次将char数组或float数组存储在一个联合中,不能一次都存储,并且不能(至少不应该)使用C ++中的联合在float和char表示形式之间进行转换。
您的代码中发生了什么?
// static_cast<char*> from string is forbidden in iso C++. It's better to use should use at least std::string.c_str()
// or use char char_data_[sizeof("abcdefghijklmnopqrstuvwx"]; memcpy(char_data_, "abcdefghijklmnopqrstuvwx", sizeof(char_data_));
char *char_data_ = static_cast<char *>("abcdefghijklmnopqrstuvwx");
// you are allocating strlen("abcdefghijklmnopqrstuvwx")/4 = 24/4 = 6 bytes of memory. That's memory for 1 and a half float numbers.
float *float_data_ = reinterpret_cast<float *>(malloc(strlen(char_data_)/sizeof(float)));
// this will print '24\n'
printf("%ld\n", strlen(char_data_));
// you are copying 6 bytes of data from char_data_ to float_data_
// now float_data_ contains "abcdef" without '\0'
memcpy(float_data_, reinterpret_cast<float *>(char_data_), strlen(char_data_)/sizeof(float));
// this will print 16777999408082104352768.000000 on the first loop, which is "abcd" in hex in ascii
// then this invokes undefined behaviour cause of out of bound access
// you are trying to access elements number 2, 3, 4, 5 while float_data_ points to only 6 bytes, which is 1,5 float numbers, so even float_data_[1] is out of bound and undefined behaviour
for ( auto n = 0 ; n < strlen(char_data_)/sizeof(float); n++) {
printf("%f\n", *(float_data_ + n));
}