使用 int 数组的一部分时的字节顺序

发布于 2024-12-11 19:19:38 字数 1081 浏览 0 评论 0原文

我正在尝试从 uint8_t 数组中提取值。 但我很难理解这些在内存中是如何表示的。

#include <cstdio>
#include <cstring>
#include <stdint.h>
int main(){
  uint8_t tmp1[2];
  uint16_t tmp2 = 511;//0x01 + 0xFF = 0x01FF
  tmp1[0] = 255;//0xFF
  tmp1[1] = 1;//0x01
  fprintf(stderr,"memcmp = %d\n",memcmp(tmp1,&tmp2,2));


  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+0));
  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+1));

  fprintf(stderr,"2xuint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);
  return 0;
}

所以我有一个数据类型为 uint8_t 的 2 元素长数组。我有一个变量 uint16_t。 因此,当我在小端机器上获取值 511 时,我会假设它在内存中布局为

0000 0001 1111 1111

但是当我使用 memcompare 时,它​​看起来实际上被表示为

1111 1111 0000 0001 

那么小端序仅在每个字节“内”使用? 由于 tmp1[1] 中设置的单个位计数为 256,即使它在我的流中更“正确”。每个字节(不是位)的值因此是bigendian 吗?我对此有点困惑。

另外,如果我想强制 fprint 打印输出,我的 2xuint8_t 作为单个 uint16_t,我该怎么做。下面的代码不起作用,它只打印出第一个字节。

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);

提前致谢

I'm trying to pullout values from a uint8_t array.
But I'm having troubles understanding how these are represented in the memory.

#include <cstdio>
#include <cstring>
#include <stdint.h>
int main(){
  uint8_t tmp1[2];
  uint16_t tmp2 = 511;//0x01 + 0xFF = 0x01FF
  tmp1[0] = 255;//0xFF
  tmp1[1] = 1;//0x01
  fprintf(stderr,"memcmp = %d\n",memcmp(tmp1,&tmp2,2));


  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+0));
  fprintf(stderr,"first elem in uint8 array  = %u\n",(uint8_t) *(tmp1+1));

  fprintf(stderr,"2xuint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);
  return 0;
}

So i have an 2 element long array of datatype uint8_t. And I have a single variable uint16_t.
So when I take the value 511 on my little endian machine, I would assume this is layed out in memory as

0000 0001 1111 1111

But when I use memcompare it looks like it is actually being represented as

1111 1111 0000 0001 

So little endianness is only used "within" each byte?
And since the single bit that is set in the tmp1[1] counts as 256, even though it is further "right" in my stream. The values for each byte (not bit), is therefore bigendian? I'm abit confused about this.

Also if I want to coerce an fprint, to printout, my 2xuint8_t as a single uint16_t, how do I do this. The code below doesn't work, it only printouts the first byte.

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",(uint16_t) *tmp1);

Thanks in advance

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

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

发布评论

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

评论(3

岁月蹉跎了容颜 2024-12-18 19:19:39

不要将字节序视为“字节内”。将其视为“字节排序”。 (也就是说,实际的位顺序并不重要,因为人类通常以大尾数法读取值。)如果有助于想象这些位在小尾数法机器上颠倒,那么您可以这样想象。 (在这种情况下,您的示例看起来像 1111 1111 1000 0000,但正如我所说,人类通常不会读取最重要的值位于右侧的数字......但是您可能想想象这就是计算机看待事物的方式,如果它可以帮助您理解小端字节序。)

在小端字节序机器上,0xAABBCCDD将被视为0xDD内存中的 0xCC 0xBB 0xAA,正如您所看到的。在大端机器(例如 PPC 盒子)上,您会在内存中看到与写出 32 位字时相同的顺序。

Don't think of endianness as "within bytes". Think of it as "byte ordering". (That is, the actual bit ordering never matters because humans typically read values in big-endian.) If it helps to imagine that the bits are reversed on a little-endian machine, you can imagine it that way. (in that case, your example would have looked like 1111 1111 1000 0000, but as I said, humans don't typically read numbers such that the most significant values are to the right...but you might want to imagine that's how the computer sees things, if it helps you understand little-endian.)

On a little endian machine, 0xAABBCCDD would be seen as 0xDD 0xCC 0xBB 0xAA in memory, just as you are seeing. On a big-endian machine (such as a PPC box) you'd see the same ordering in-memory as you see when you write out the 32-bit word.

命硬 2024-12-18 19:19:39

首先,如果您想 100% 确定变量以正确的顺序存储在内存中,则应该将它们放入结构中。

然后请注意,memcmp() 将您提供的输入视为字节序列,因为它对您提供的数据的性质没有任何假设。例如,考虑以下代码:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char** argv) {
    int32_t a, b;
    a = 1;
    b = -1;
    printf( "%i\n", memcmp( &a, &b, sizeof( int32_t ) ) );
}

它在我的小端机器上输出 -254,不管 a > > 是否存在。 b.这是因为它不知道内存实际是什么,所以它像 uint8_t 数组一样比较它们。

如果您确实想可视化数据在您的计算机上的表示方式,您可以首先使用 fwrite 将结构写入文件中,然后使用您最喜欢的十六进制编辑器打开它(根据我的经验,wxHexEditor 非常适合告诉您数据如何表示)看看它是否是 X 位 Y-endian 整数)。来源如下:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    uint8_t tmp1[2];
    uint16_t tmp2;
} mytmp;

int main(int argc, char** argv) {
    mytmp tmp;
    tmp.tmp1[0] = 255;
    tmp.tmp1[1] = 1;
    tmp.tmp2 = 511;

    FILE* file = fopen( "struct-dump", "w" );
    fwrite( &tmp, sizeof( mytmp ), 1, file );
    fclose( file );
}

至于将 uint8_t 数组视为 uint16_t,您可能需要声明一个 union 或使用指针强制。

First, if you want be 100% sure that your variables are stored in right order in memory, you should put them in a struct.

Then note that memcmp() treats input you give it as a sequence of bytes, since it has no assumptions regarding the nature of the data you give it. Think, for example, of the following code:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char** argv) {
    int32_t a, b;
    a = 1;
    b = -1;
    printf( "%i\n", memcmp( &a, &b, sizeof( int32_t ) ) );
}

It outputs -254 on my little-endian machine regardless of fact that a > b. This is because it has no ideas about what the memory actually is, so it compares them like an array of uint8_t.

If you actually want to visualize how the data is represented on your machine, you may first use fwrite to write a struct into the file and then open it with your favorite hex editor (in my experience, wxHexEditor is great in telling you how the data looks if it is X-bit Y-endian ingeter). Here's the source:

#include <stdio.h>
#include <stdint.h>

typedef struct {
    uint8_t tmp1[2];
    uint16_t tmp2;
} mytmp;

int main(int argc, char** argv) {
    mytmp tmp;
    tmp.tmp1[0] = 255;
    tmp.tmp1[1] = 1;
    tmp.tmp2 = 511;

    FILE* file = fopen( "struct-dump", "w" );
    fwrite( &tmp, sizeof( mytmp ), 1, file );
    fclose( file );
}

As for treating an array of uint8_t as uint16_t, you would probably want to declare a union or use pointer coercion.

予囚 2024-12-18 19:19:38

你对你的期望的假设是倒退的。您的观察结果与小端表示一致。要回答你的最后一个问题,它看起来像这样:

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",*(uint16_t*)tmp1);

Your assumption of what you expect is backwards. Your observation is consistent with little-endian representation. To answer your last question, it would look like this:

fprintf(stderr,"2x uint8_t as uint16_t  = %u\n",*(uint16_t*)tmp1);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文