如果我在 8 位处理器的内存中有一个 int32 类型的整数,比如 8051,我如何识别该整数的字节序?它是编译器特定的吗?我认为这在通过串行线路等发送多字节数据时很重要。
7 回答
对于不支持更宽整数的 8 位微控制器,存储在内存中的整数的字节顺序确实取决于编译器编写者。
在 8051 上广泛使用的 SDCC 编译器以 little-endian 格式存储整数(该编译器的用户指南声称它在该架构上更有效,因为存在用于递增数据指针但没有递增的指令用于递减)。
如果处理器有任何作用于多字节值的操作,或者有一个多字节寄存器,它就有可能具有字节序。
http://69.41.174.64/forum/printable.phtml?id=14233&thread=14207表明 8051 在不同的地方混合了不同的字节序。
字节序特定于 CPU 架构。由于编译器需要以特定 CPU 为目标,因此编译器也会知道字节顺序。因此,如果您需要通过串行连接、网络等发送数据,您可能希望使用内置函数将数据按网络字节顺序排列——尤其是当您的代码需要支持多种架构时。
有关详细信息,请参阅:http ://www.gnu.org/s/libc/manual/html_node/Byte-Order.html
这不仅取决于编译器 - '51 有一些本机 16 位寄存器(DPTR、标准中的 PC、ADC_IN、DAC_OUT 等变体),编译器必须遵守给定的字节序 - 但除此之外,编译器是免费使用它喜欢的任何字节序或您在项目配置中选择的字节序...
整数中没有字节序。您无法仅通过查看字节来确定它是大端还是小端。您只需要知道:例如,如果您的 8 位处理器是 little endian,并且您收到一条您知道是 big endian 的消息(因为,例如,现场总线系统定义了 big endian),您必须转换值超过 8 位。您需要对其进行硬编码或在系统上对要交换的字节进行一些定义。
请注意,交换字节很容易。您可能还必须交换位域中的位,因为位域中的位顺序是特定于编译器的。同样,您基本上必须在构建时知道这一点。
unsigned long int x = 1;
unsigned char *px = (unsigned char *) &x;
*px == 0 ? "big endian" : "little endian"
如果 x 被赋值为 1,那么值 1 将在最低有效字节中。如果我们然后将 x 转换为指向字节的指针,则该指针将指向 x 的最低内存位置。如果该内存位置为 0,则为大端,否则为小端。
#include <stdio.h>
union foo {
int as_int;
char as_bytes[sizeof(int)];
};
int main() {
union foo data;
int i;
for (i = 0; i < sizeof(int); ++i) {
data.as_bytes[i] = 1 + i;
}
printf ("%0x\n", data.as_int);
return 0;
}
解释输出由您决定。