【问题标题】:C - Store float to char array and reverseC - 将浮点数存储到字符数组并反转
【发布时间】:2019-08-16 15:54:13
【问题描述】:

假设我有这个浮动:

float f;

我想将它存储在一个字符数组中:

char bytes[4];

然后反转数组回到浮动。 有什么帮助吗?提前致谢。

编辑:这是代码,它可以工作:

float amount = 0.01;
char array[sizeof(float)];
memcpy(array, &amount, sizeof(float));

float f;
char bytes[4] = {array[0], array[1], array[2], array[3]};
memcpy(&f, bytes, sizeof f);

【问题讨论】:

  • “反向”是指简单地将字节从数组移回float,或者您的意思是颠倒字节的顺序,使最后一个字节在前,第一个字节在后,然后等等?
  • @EricPostpischil 我的意思是简单地将字节从数组移回浮点数。
  • @ButiriDan 我需要存储它,而不是呈现它。
  • 编辑中发布的代码对我有用,并附加了printf("%g\n", f);(并且还包含在#include <stdio.h> / #include ` / int main(void) { … } 中)。它打印“0.01”。

标签: c arrays memory floating-point byte


【解决方案1】:

假设sizeof(float)为4,则可以通过memcpyfloat变量的值表示复制到char数组中:

#include <string.h>

void do_something(float f) {
    char bytes[4];
    memcpy(bytes, &f, 4);
    // ...
}

您可以通过再次调用memcpy() 来反转该操作(即,将表示复制回来),将前两个参数反转。在这两者之间,您可以操作字节——例如,反转它们——但在这种情况下,语言不支持float 对结果字节序列的解释。

【讨论】:

  • 这是否意味着没有办法按照我的要求去做?
  • @evannemo,您必须根据问题中的 cmets 澄清您的要求,但如果我正确理解那是什么,那么我相信这个答案准确地描述了如何做到这一点.
【解决方案2】:

您可以使用memcpy,但最好包含_Static_assert 来检查大小:

#include <stdio.h>
#include <string.h>

int main(void)
{
    float f = 10./7;
    char  bytes[4];

    // Check that float is the same size as the array we provide.
    _Static_assert(sizeof f == sizeof bytes, "float mus be four bytes.");

    // Copy bytes from the float to the array.
    memcpy(bytes, &f, sizeof bytes);

    // Show the bytes.
    for (size_t i = 0; i < sizeof bytes; ++i)
        printf("Byte %zu is 0x%02x.\n", i, (unsigned char) bytes[i]);

    // Copy the bytes from the array to another float.
    float g;
    memcpy(&g, bytes, sizeof g);

    // Show the resulting float.
    printf("g = %g.\n", g);
}

【讨论】:

  • 虽然从 float 复制到 char 数组有效,但反之无效。我在 printf 上一直得到 0.0。
  • @evannemo:您复制代码时可能已更改代码。我在发布之前编译并执行了。之后;我从网页上复制代码并编译并执行,它打印“g = 1.42857”。
【解决方案3】:
  • 将浮点数转换为字符数组sprintf
  • 将 char 数组转换为浮点 atof
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char array[10];
    float val;

    sprintf(array, "%f", 3.123);
    val = atof(array);

    printf("%s\n%f", array, val);

    return 0;
}

输出

3.123000
3.123000

【讨论】:

    【解决方案4】:

    memcpy 是一个需要头文件“string.h”的内置函数。根据您的应用场景,如果您想避免使用 memcpy 加上您的 char 数组是 4 字节对齐的,这是我在类似 gcc 的编译器中基于静态转换的首选方式。

    将数量(浮点数)复制到数组(char*)

    float amount  = 0.01;
    char  array[4] __attribute__((aligned(4)));
    *((float *)array) = amount; 
    

    将字节 (char*) 复制到 f (float)

    float f;
    char bytes[4] __attribute__((aligned(4)));
    f =  *((float *) bytes);
    

    另外,我相信还有一种方法可以在任何编译器下工作,无论字节对齐如何:

    首先,定义一个具有四个字节的虚拟结构(浮点数占用四个字节。或者,使用 sizeof(float) 代替 4)。

    typedef struct {char fourBytes[4]; } FourBytes ; 
    

    如下使用:

    float amount     = 0.01;
    char  array[4]  ;
    
    // copy from amount to array
    *((FourBytes *)array) = *((FourBytes *) (&amount));
    
    // copy from array to amount
     *((FourBytes *) (&amount)) = *((FourBytes *)array) ;
    
    

    从功能的角度来看,第三种选择可能只是使用联合结构:

    union DATA
    {
        float f;
        char  array[4];
    }; // array is forced to 4-byte aligned
    

    如下使用:

    union DATA data1;
    union DATA data2;
    
    // copy data between the two
    data1.f = data2.f
    

    【讨论】:

    • 这就是无效。由于可能的未对齐访问和严格的别名冲突,您的演员有未定义的行为 - 正确的方法是使用循环或 memcpy。如果可以的话,编译器知道如何优化memcpy
    • 你绝对是对的。 char 数组应该是 4 字节对齐的。将发出严格的混叠违规警告。我仍然在这里保留答案,以防万一,它在某些情况下可能是相关的,但要牢记警告
    猜你喜欢
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-22
    • 1970-01-01
    相关资源
    最近更新 更多