C 结构以十六进制打印的位。

huangapple go评论51阅读模式
英文:

C structure with bits printing in hexadecimal

问题

我已经定义了如下的结构:

struct {
UCHAR DSatasetMGMT : 1;
UCHAR AtriburDeallocate : 1;
UCHAR Reserved6 : 6;
UCHAR Reserved7 : 7;
UCHAR DSatasetMGMTComply : 1;
} DatasetMGMTCMDSupport;


这是一个用位表示的2字节结构。如何以十六进制打印整个结构的2字节数据?我尝试了以下两种方式:

"DatasetMGMTCMDSupport : 0x%04X\n"

0x%04I64X\n


但没有得到预期的结果。

在64位的Windows系统上,使用0x%04X\n时,我得到了0x3DC18003,而正确的数据应该是0x8003。

我需要知道如何以十六进制打印这个2字节的结构。
英文:

I have defined a structure as below

   struct {
        UCHAR   DSatasetMGMT : 1;
        UCHAR   AtriburDeallocate : 1;
        UCHAR   Reserved6 : 6;
        UCHAR   Reserved7 : 7;
        UCHAR   DSatasetMGMTComply : 1;
    }DatasetMGMTCMDSupport;

It is a 2 byte structure represented in bits. How should I print the whole 2 bytes of structure in hexadecimal. I tried

"DatasetMGMTCMDSupport                          :   0x%04X\n"

And

0x%04I64X\n

But not getting expected result.

I am getting 0x3DC18003 with 0x%04X\n while the correct data is 0x8003 "

I am using 64 bit windows system.

I need to know how to print 2 byte structure in hexadecimal.

答案1

得分: 2

尝试使用 0x%04hx\n。这告诉 printf 只打印出两个字节。您可以在这里了解更多信息:https://en.wikipedia.org/wiki/Printf_format_string#Length_field

相比之下,在 0x%04I64X\n 中的 I64 告诉 printf 打印出一个 64 位整数,即 8 字节,而 0x%04X\n 告诉它打印出默认大小的整数,这在您的系统上可能是 4 个字节。

宽度 04 指定了最小宽度。由于值需要更多位数,它们会被打印出来。

英文:

Try using 0x%04hx\n. This tells printf to print out only the two bytes. You can read more about it here: https://en.wikipedia.org/wiki/Printf_format_string#Length_field

In contrast, the I64 in 0x%04I64X\n tells printf to print out a 64 bit integer, which is 8 bytes, and 0x%04X\n tells it to print out a default-size integer, which might be 4 bytes on your system.

The width 04 specifies a minimum width. Since the value needs more digits, they are printed.

答案2

得分: 2

从C标准的角度来看,您不能依赖于位字段的特定布局。因此,任何解决方案充其量都具有实现定义的行为。

话虽如此,您可以获得所期望的输出。这个结构适合2个字节,如果您打印 sizeof(DatasetMGMTCMDSupport),应该得到结果2。

DatasetMGMTCMDSupport 的字节表示可以被打印出来,这似乎是您的尝试,但由于您的系统整数大小为4,会包括两个额外的字节。为了修复这个问题,可以执行以下操作:

#include <stdint.h>
#include <string.h>
#include <stdio.h>
...
    uint16_t a;
    memcpy(&a, &DatasetMGMTCMDSupport, sizeof(a));
    printf("0x%04X", (unsigned)a);

这将把 DatasetMGMTCMDSupport 的2个字节复制到一个2字节整数变量中,并打印这2个字节的十六进制表示。如果您的系统是小端序的,您应该会看到 0x8003

一个更一般的方法是直接打印 DatasetMGMTCMDSupport 的字节:

    for(unsigned i = 0; i < sizeof(DatasetMGMTCMDSupport); i++)
    {
        printf("%02X", (unsigned)((unsigned char *)&DatasetMGMTCMDSupport)[i]);
    }

这很可能会打印出 0380(请注意字节顺序:首字节先打印)。

要颠倒字节顺序很简单:

    for(unsigned i = 0; i < sizeof(DatasetMGMTCMDSupport); i++)
    {
        printf("%02X", (unsigned)((unsigned char *)&DatasetMGMTCMDSupport)[sizeof(DatasetMGMTCMDSupport)-1-i]);
    }

这应该给出 8003

英文:

From a C Standard point of view, you cannot rely on a particular layout of bit fields. Hence, any solution will at best have implementation-defined behaviour.

That being said, your expected output can be obtained. The structure fits in 2 bytes and if you print sizeof(DatasetMGMTCMDSupport) it should give the result 2.

The byte representation of DatasetMGMTCMDSupport can be printed and that is what you were attempting, but since your system has integer size 4, two additional bytes are included. To fix this, the following can be done:

#include &lt;stdint.h&gt;
#include &lt;string.h&gt;
#include &lt;stdio.h&gt;
...
    uint16_t a;
    memcpy(&amp;a, &amp;DatasetMGMTCMDSupport, sizeof(a));
    printf(&quot;0x%04X&quot;, (unsigned)a);

This copies the 2 bytes of DatasetMGMTCMDSupport into a 2-byte integer variable and prints the hexadecimal representation of those 2 bytes only. If you are on a little-endian system, you should see 0x8003.

A more general approach would be to directly print the bytes of DatasetMGMTCMDSupport:

    for(unsigned i = 0; i &lt; sizeof(DatasetMGMTCMDSupport); i++)
    {
        printf(&quot;%02X&quot;, (unsigned)((unsigned char *)&amp;DatasetMGMTCMDSupport)[i]);
    }

This will most likely print 0380 (notice the byte order: first byte printed first).

To reverse the byte order is straightforward:

    for(unsigned i = 0; i &lt; sizeof(DatasetMGMTCMDSupport); i++)
    {
        printf(&quot;%02X&quot;, (unsigned)((unsigned char *)&amp;DatasetMGMTCMDSupport)[sizeof(DatasetMGMTCMDSupport)-1-i]);
    }

which should give 8003.

huangapple
  • 本文由 发表于 2023年2月16日 14:07:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/75468434.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定