0

几个星期以来,我一直在用一些书轻轻地学习 C。

int main(void)
{
    float num = 3.15;
    int *ptr = (int *)# //so I can use line 8 and 10

    for (int i = 0; i < 32; i++)
    {
        if (!(i % 8) && (i / 8))
            printf(" ");
        printf("%d", *ptr >> (31 - i) & 1);
    }

    return 0;
}

output : 01000000 01001001 10011001 10011010

正如您3.15在单精度float中看到的那样01000000 01001001 10011001 10011010。所以让我们说ptr点地址0x1efb40

以下是问题:

  1. 正如我在书中所理解的那样,前 8 位num数据存储在 中0x1efb40,第二个 8 位存储在 中0x1efb41,接下来的 8 位存储在 中0x1efb42,最后 8 位存储在 中0x1efb43。我对吗?

  2. 如果我是对的,有什么方法可以直接使用十六进制地址值访问第二个 8 位0x1efb41?因此我可以将数据更改为类似的东西11111111吗?

4

3 回答 3

4

数据类型中的字节顺序称为字节顺序,并且是系统特定的。您首先用最低有效字节 (LSB) 描述的内容称为小端序,您可以在基于 x86 的处理器上找到它。

至于访问表示的特定字节,您可以使用指向 an 的指针来unsigned char指向相关变量以查看特定字节。例如:

 float num = 3.15;
 unsigned char *p = (unsigned char *)&num;
 int i;

 for (i=0; i<sizeof(num); i++) {
     printf("byte %d = %02x\n", i, p[i]);
}

请注意,这只允许通过字符指针访问字节,而不是int *,因为后者违反了严格的别名。

于 2018-07-25T15:11:19.337 回答
1

您编写的代码实际上不是有效的 C。C 有一条称为“严格别名”的规则,该规则规定如果内存区域包含一种类型的值(即float),则不能像访问另一种类型(即int)。这条规则起源于一些性能优化,可以让编译器生成更快的代码。我不能说这是一个明显的规则,但它就是规则。

您可以使用union. 如果您创建一个类似的联合union { float num, int numAsInt },您可以存储一个浮点数,然后将其作为整数读取。结果未指定。或者,您总是被允许以字符的形式访问值的字节(只是不能更大)。 char被给予特殊处理(大概是为了让您可以将数据缓冲区复制为字节,然后将其转换为您的数据类型并访问它,这在网络堆栈等低级代码中经常发生)。

欢迎来到学习 C 的有趣角落。有未指定的行为和未定义的行为。非正式地,未指明的行为表示“我们不会说会发生什么,但它会是合理的。” C规范不会说明字节的顺序。但它会说你会得到一些字节。未定义的行为更令人讨厌。未定义的行为表明任何事情都可能发生,从编译器错误到运行时的异常,再到什么都没有(让你认为你的代码是有效的,但实际上它不是)。

至于值,dbush 在他的回答中指出,字节的顺序是由您所在的平台定义的。您看到的是 IEE754 浮点数的“小端”表示。在其他平台上,可能会有所不同。

于 2018-07-25T15:13:48.957 回答
0

联合双关语更安全:

#include <stdio.h>

typedef     union
    {
        unsigned char uc[sizeof(double)];
        float f;
        double d;
    }u_t;

void print(u_t u, size_t size, int endianess)
{
    size_t start = 0;
    int increment = 1;

    if(endianess)
    {
        start = size - 1;
        increment = -1;
    }

    for(size_t index = 0; index < size; index++)
    {
        printf("%hhx ", u.uc[start]);
        start += increment;
    }
    printf("\n");
}


int main(void) 
{
    u_t u;  
    u.f = 3.15f;

    print(u, sizeof(float),0);
    print(u, sizeof(float),1);

    u.d = 3.15;
    print(u, sizeof(double),0);
    print(u, sizeof(double),1);
    return 0;
}

你可以自己测试一下:https ://ideone.com/7ABZaj

于 2018-07-25T15:28:01.363 回答