位字节顺序如何影响 C 中的按位移位和文件 IO?

发布于 2024-10-28 11:02:40 字数 1408 浏览 10 评论 0 原文

LB为两台机器。 L 从 LSB 排序其 (最低有效位)到 MSB(最高有效位),同时 B 顺序 从 MSB 到 LSB。或者,换句话说,L 使用 Little Endian,而 B 使用 Big Endian bit - 不要与字节排序混淆。

问题 1 已解决

我们正在编写以下我们希望可移植的代码:

#include <stdio.h>

int main()
{
    unsigned char a = 1;
    a <<= 1;

    printf("a = %d\n", (int) a);

    return 0;
}

L 上,它将打印 2,但是在 B 上会发生什么>?是否会改变 1 输出并打印 0?

解决方案: 6.5.7 中的 C99 定义表明,至少在 无符号整数类型,<<>> 将乘以 2 并除以 2 分别。

问题 2:

我们正在编写以下希望可移植的代码:

READ 程序:

/* program READ */
#include <stdio.h>

int main()
{
    FILE* fp;
    unsigned char a;

    fp = fopen("data.dat", "rb");
    fread(&a, 1, 1, fp);
    fclose(fp);

    return 0;
}

和 WRITE 程序:

/* program WRITE */
#include <stdio.h>

int main()
{
    FILE* fp;
    unsigned char a = 1;

    fp = fopen("data.dat", "wb");
    fwrite(&a, 1, 1, fp);
    fclose(fp);

    return 0;
}

如果我们在 L 上运行 WRITE,将数据文件移动到 B 会发生什么强>和 在那里运行 READ?如果我们在 B 上运行 WRITE,然后在 L 上运行 READ 呢?

抱歉,如果这是常见问题解答。我用谷歌搜索了几个小时但没有运气。

Let L and B be two machines. L order its bits from LSB
(Least Significant Bit) to MSB (Most Significant Bit) while B order
from MSB to LSB. Or, in other words, L uses Little Endian while
B uses Big Endian bit - not to be confused with byte - ordering.

Problem 1 SOLVED:

We are writing the following code which we want to be portable:

#include <stdio.h>

int main()
{
    unsigned char a = 1;
    a <<= 1;

    printf("a = %d\n", (int) a);

    return 0;
}

on L, it will print 2, but what happens on B? Will it shift the
1 out and print 0?.

SOLUTION: The C99 definition at 6.5.7 says it that, at least on
unsigned integer types, << and >> will multiply and divide by 2
respectively.

Problem 2:

We are writing the following code which we want to be portable:

READ program:

/* program READ */
#include <stdio.h>

int main()
{
    FILE* fp;
    unsigned char a;

    fp = fopen("data.dat", "rb");
    fread(&a, 1, 1, fp);
    fclose(fp);

    return 0;
}

and WRITE program:

/* program WRITE */
#include <stdio.h>

int main()
{
    FILE* fp;
    unsigned char a = 1;

    fp = fopen("data.dat", "wb");
    fwrite(&a, 1, 1, fp);
    fclose(fp);

    return 0;
}

what happens if we run WRITE on L, move the data file to B and
run READ there? And if we run WRITE on B and then READ on L?

Sorry if this is a FAQ. I googled for hours without luck.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

惯饮孤独 2024-11-04 11:02:41

位字节顺序不会影响以字节为单位存储在磁盘上的数据。字节尾数会。

位字节顺序对于串行接口来说很重要,在串行接口中,一次发送一位字节,并且发送者和接收者需要就字节顺序达成一致。例如,SPI 设备中的位顺序有所不同,您需要在尝试读取之前参考数据表从设备。

以下是 Wikipedia 关于位字节序的说法:

术语位字节序或位级
很少使用字节顺序
谈论一个代表
储值,因为它们只是
对于稀有计算机有意义
每个人的架构
位具有唯一的地址。他们是
但用于指代
比特的传输顺序
串行介质。最常见的是这个顺序
由透明地管理
硬件,是位级模拟
小尾数(低位优先),
尽管存在需要的协议
相反的顺序(例如I²C)。在
网络,有关的决定
位的传输顺序已确定
在数据链接的最底部
OSI 模型层。

在您的情况下,物理硬盘驱动器接口定义了位顺序,而不管要读取或写入它的处理器如何。

Bit Endianness doesn't affect data stored on disks in bytes. Byte Endianness will.

Bit Endianness is something that matters for serial interfaces where a byte is sent one bit at a time, and the sender and receiver need to agree on the byte order. For example, bit order in SPI devices varies and you need to reference the data sheet before attempting to read from the device.

Here's what Wikipedia says on bit endianness:

The terms bit endianness or bit-level
endianness are seldom used when
talking about the representation of a
stored value, as they are only
meaningful for the rare computer
architectures where each individual
bit has a unique address. They are
used however to refer to the
transmission order of bits over a
serial medium. Most often that order
is transparently managed by the
hardware and is the bit-level analogue
of little-endian (low-bit first),
although protocols exist which require
the opposite ordering (e.g. I²C). In
networking, the decision about the
order of transmission of bits is made
in the very bottom of the data link
layer of the OSI model.

In your case, the physical hard drive interface defines the bit order, regardless of the processor that's going to read or write it.

吻风 2024-11-04 11:02:41

实际上并不存在位字节序这样的东西,至少就 C 而言是这样。根据规范,CHAR_BIT 必须至少为 8,因此访问任何小于该值的对象对于标准 C 程序来说几乎没有意义。无论硬件如何存储字节(首先是 LSB 还是 MSB),它都不会影响您的程序。 myVar & 1 在任何一种情况下都会返回正确的位。

如果您需要与某种串行接口交互并从中重构字节,那就是另一回事了。您自己的机器的“位字节顺序”仍然不会影响任何内容,但接口的位顺序肯定会影响。

现在,关于您的具体问题和您所展示的程序。您的程序几乎 100% 可移植。位字节顺序和字节字节顺序都不会影响它们。 可能影响它们的是CHAR_BIT在每个平台上是否不同。一台计算机写入的数据可能多于另一台计算机读取的数据,反之亦然。

There isn't really such a thing as bit-endianness, at least as far as C is concerned. CHAR_BIT has to be at least 8 according to the spec, so accesses to any objects smaller than that is pretty much meaningless to a standard C program. Regardless of how the hardware stores a byte - LSB or MSB first - it doesn't affect your program at all. myVar & 1 returns the right bit in either case.

If you need to interact with some kind of serial interface and reconstitute bytes from it, that's a different story. Your own machine's 'bit-endianness' still doesn't affect anything, but the bit order of the interface certainly does.

Now, as to your specific question and the program you've shown. Your programs are almost 100% portable. Neither bit- nor byte-endianness affects them. What might affect them is if CHAR_BIT were different on each platform. One computer might write more data than the other one would read, or vice versa.

夜清冷一曲。 2024-11-04 11:02:41

number>>nnumber< 不会向右和向左推和拉位。它们将 number 除以 2^n。值得注意的是,如果 n 为负数或大于 number 数据类型的宽度,则不会定义这些移位的行为。

根据 第 6.5.7 节C99标准

E1的结果<< E2是E1左移E2位的位置;空出的位用零填充。 如果 E1 具有无符号类型,则结果值为 E1 × 2^E2,比结果类型中可表示的最大值减少模一。如果 E1 具有有符号类型和非负值,并且 E1 × 2^E2 可在结果类型中表示,则这就是结果值;否则,行为未定义。

E1的结果>> E2是E1右移E2位的位置。如果 E1 为无符号类型,或者 E1 为有符号类型且为非负值,则结果值为 E1 / 2^E2 商的整数部分。如果 E1 具有有符号类型和负值,则结果值是实现定义的。

对于所有编译器关心的问题,这些位可以垂直堆叠:)

The number>>n and number<<n do not push and pull bits right and left. They divide and multiply number by 2^n. It's worth noting that the behavior of these shifts is not defined if n is negative or is larger than the width of the datatype of number.

According to section 6.5.7 from the C99 standard:

The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

For all the compiler cares, the bits could be stacked vertically :)

滥情空心 2024-11-04 11:02:41

位移位不受字节顺序的影响。二进制文件 I/O 通常是,但在你的情况下不是,因为你只写一个字节。

Bit-shifting is not affected by endianness. Binary file I/O normally is, but not in your case since you are only writing a single byte.

心是晴朗的。 2024-11-04 11:02:41

字节序不会影响您,除非 a) 您使用与写入时不同的类型从内存中读取某些内容,或者从使用不同字节序的机器写入的文件中读取某些内容。

int data;
char charVal;

*data = 1;
charval = *((char *) data);  // Different result based on endianness

或者您的示例二,假设您使用的类型大于 char。

Endianness will not affect you unless a) you read something from memory using a different type than you used to write it to, or if you read something from a file that was written with a machine using different endianness.

i.e.

int data;
char charVal;

*data = 1;
charval = *((char *) data);  // Different result based on endianness

Or your example two, assuming you're using a type larger than char.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文