Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 无法看到填充_C - Fatal编程技术网

C 无法看到填充

C 无法看到填充,c,C,我有一个这样的结构: typedef struct la { bool b; union { uint16_t i; struct { uint8_t j; uint8_t k; }; }; } la_t; int main() { la_t a; a.b = 0x01c3; a.i = 0xa067; printf("%x", a.b); return 0; } 我知道在1字节的boo

我有一个这样的结构:

typedef struct la {
  bool b;
  union {
    uint16_t i;
    struct {
      uint8_t j;
      uint8_t k;
    };
  };
} la_t;

int main()
{

    la_t a;
    a.b = 0x01c3;
    a.i = 0xa067;

    printf("%x", a.b);

    return 0;
}

我知道在1字节的bool后面有一个填充,sizeof(la_t)是4。然而,即使我给bool分配了一个2字节的值,它也只返回01,第一个字节。如何访问/查看带有数据的填充字节?

因为布尔类型就是这样工作的。它要么为真(
1
),要么为假(
0

编译器将在布尔变量
b
的赋值中,将所有非零值转换为true,将所有非零值转换为false(有关详细信息,请参阅小节)



“查看”结构中可能的填充的唯一方法是逐字节查看原始二进制形式。但是请注意,虽然允许填充,但它仍然作为实现细节保留了很多,并且可能的填充字节的内容是不确定的。任何读取数据(或更糟的是写入数据)的尝试都被视为UB。

您不能合法地访问填充,但您可以通过考虑大小和偏移来证明其存在。请注意,分配给
bool
的任何非零值都会导致
bool
保持
1
aka
true
;只有指定的零值将以
0
false
结束

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

typedef struct la
{
    bool b;
    union
    {
        uint16_t i;
        struct
        {
            uint8_t j;
            uint8_t k;
        };
    };
} la_t;

int main(void)
{
    la_t a;
    a.b = 0x01c3;

    printf("%x\n", a.b);
    a.b = 0x0100;
    printf("%x\n", a.b);
    a.b = 0x0000;
    printf("%x\n", a.b);

    printf("Size   of a.b = %zu\n", sizeof(a.b));
    printf("Offset of a.b = %zu\n", offsetof(la_t, b));
    printf("Size   of a.i = %zu\n", sizeof(a.i));
    printf("Offset of a.i = %zu\n", offsetof(la_t, i));
    printf("Size   of a   = %zu\n", sizeof(a));

    return 0;
}
如您所见,在布尔值
b
和包含
i
的匿名联合之间有1个字节的未请求空间(1个填充字节)


您可以将整个结构复制到一个字节数组(
memmove()
memcpy()
)中,然后检查复制的字节值,但这几乎不合法,可能不可靠。与此相反,查看填充字节中内容的唯一方法是再次通过复制机制。请注意,对结构的其他成员的赋值可能会修改填充字节,也可能不会修改填充字节。

您不能。它已被截断。您需要先memcpy该值,然后memcpy返回以读取它。或使用偏移量
b
写入不是联合的一部分。通常,您不能通过访问成员本身来访问成员之间的填充。您需要使用
char
指针直接访问结构的字节。尝试读取或写入填充字节不是未定义的行为。C中的对象由字节组成(C 2018 6.2.6 2)。明确允许您通过指向字符类型(6.2.6.4和6.3.2.3.7)的指针读取这些字节。这意味着您可以编写它们,因为这就是指定
memcpy
工作的方式(7.24.2.1.2)。当修改结构成员时,填充字节确实采用未指定的值(6.2.6)。
1
1
0
Size   of a.b = 1
Offset of a.b = 0
Size   of a.i = 2
Offset of a.i = 2
Size   of a   = 4