Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.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++_C_Floating Point_Unions - Fatal编程技术网

C++ 将浮点转换为字节数组的程序中的运行时错误

C++ 将浮点转换为字节数组的程序中的运行时错误,c++,c,floating-point,unions,C++,C,Floating Point,Unions,我得到了一个浮点变量,想知道它的字节表示是什么。所以我去了IDEOne,并且这样做了。但是,令我惊讶的是,它会导致运行时错误: #include <stdio.h> #include <assert.h> int main() { // These are their sizes here. So just to prove it. assert(sizeof(char) == 1); assert(sizeof(short) == 2);

我得到了一个浮点变量,想知道它的字节表示是什么。所以我去了IDEOne,并且这样做了。但是,令我惊讶的是,它会导致运行时错误:

#include <stdio.h>
#include <assert.h>

int main()
{
    // These are their sizes here. So just to prove it.
    assert(sizeof(char) == 1);
    assert(sizeof(short) == 2);
    assert(sizeof(float) == 4);

    // Little endian
    union {
        short s;
        char c[2];
    } endian;
    endian.s = 0x00FF; // would be stored as FF 00 on little
    assert((char)endian.c[0] == (char)0xFF);
    assert((char)endian.c[1] == (char)0x00);

    union {
        float f;
        char c[4];
    } var;
    var.f = 0.0003401360590942204;
    printf("%x %x %x %x", var.c[3], var.c[2], var.c[1], var.c[0]); // little endian
}
在IDEOne上,它输出:

39 FFFFFF B2 54 4a

以及一个运行时错误。为什么会出现运行时错误,为什么b2实际上是FFFFFF b2?我猜b2是符号扩展。

字符是有符号类型。如果它的长度为8位,并且您在其中放入大于127的任何内容,它将溢出。有符号整数溢出是未定义的行为,因此,使用转换说明符打印有符号值时,该说明符应为无符号整数%x应为无符号整数,但在传递给变量printf函数时,char被提升[隐式转换]为有符号整数


底线-将char c[4]更改为unsigned char c[4],它将正常工作。

在结构中用unsigned char替换char,并添加一个返回0;最后解决了所有问题:。

你的方法完全错误。以下是如何打印常规对象的二进制表示:

template <typename T>
void hexdump(T const & x)
{
    unsigned char const * p = reinterpret_cast<unsigned char const *>(&x);
    for (std::size_t i = 0; i != sizeof(T); ++i)
    {
        std::printf("%02X", p[i]);
    }
}

结果是,您始终可以将任何对象解释为字符数组,从而显示其表示形式。

为什么需要返回0?我认为标准说它是可选的,编译器必须隐式地添加它?有没有解释为什么会这样做?@ColeJohnson AFAIK这是我们应该使用的C99。返回0;在C89中不是隐式的。未签名的问题由@H2CO3完美地解释了。作为回报,这是我第一次使用ideone.com,我不知道他们使用的是哪个C以及如何配置它。所以这只是一个猜测。抱歉。打印FFFFFF B2是因为vats.c[2]是字符,这是一种有符号的数据类型。printf将符号扩展为32位整数,因为varargs就是这样做的。您可以将其声明为无符号字符c[4]或在printf中强制转换。您是否注意到有效位数超出了限制?还可以在文字上使用“f”后缀,以指定浮点而不是双精度为什么FFFFFF b2而不是您猜测的b2是符号扩展名。但是运行时错误呢?我希望你贴出它的确切原因。符号v。unsigned、no\n、not return等@notNullGothik将值0.000340130160590942204分配给var.f时转换为float。除非您怀疑这个数字容易出现双舍入,否则在文本中添加f后缀没有什么意义。如前所述,var.c[i]在传递到printf时会升级为int,因为这是可变函数的工作方式。但是%x格式需要一个对应的无符号int。因此,除了使用一个无符号字符数组(每个字符仍将升级为int,因为C就是这样工作的),您应该调用printf%x%x%x,unsigned int var.C[3],…C99 5.2.4.2.1 p2说字符可能是有符号的,也可能是无符号的。它是实现定义的。6.3.1.1 p3中有更明确的说明:如前所述,“普通”字符是否被视为有符号字符是由实现定义的。“有符号整数溢出是未定义的行为”->在这个问题中哪里有未定义的溢出?转换为有符号类型时的溢出是由实现定义的。我没有看到任何其他类型的溢出。@PascalCuoq说是UB。也许是C++中的IB?@ H2CO3“符号整数溢出是UB”通常是正确的,但它缺乏细微差别。我不认为对于如此长度的句子,它尽可能准确,但细节是,到有符号类型的转换实际上是实现定义的。您链接的问题是32位编译器上的算术溢出,例如0x10000*0x10000。我在这个问题中看到的唯一溢出是char0xFF,大多数签名为8位char的实现都将其定义为char-1。在C99中,这是在6.3.1.3:3中。@PascalCuoq谢谢,我来看看那个子句。