为什么fwrite为uint8_t写两个字节?

rau*_*ach 2 c binary posix

在C中不是很熟练.这可能只是一个新手问题.

我试图写3个字节到文件,但最终得到4.

#include <stdio.h>
#include <stdlib.h>

struct a {
  uint8_t x;
  uint16_t y;
};

int main()
{
  struct a record = { 1, 2 };
  FILE *fp = fopen("example.bin", "w");
  fwrite(&record, sizeof(struct a), 1, fp);
  fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我最终得到:

$ hexdump -C example.bin
00000000  01 00 02 00                                       |....|
00000004
Run Code Online (Sandbox Code Playgroud)

我在期待:01 02 00.

这是我的c编译器的版本,以防这是与硬件/编译器相关的.

$ cc --version
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)

P.P*_*.P. 5

我试图写3个字节到文件,但最终得到4.

你可能会瞄准写入3个字节,但实际上写sizeof(struct a)的,因为编译器插入对齐填充的字节这很可能是4.也许您假设结构的大小等于其成员的大小总和,并且未能考虑可能的填充.

通常,编译器可以自由地插入填充以用于对齐目的(除了在结构的第一个成员之前不能有任何填充).

如果您编写单个成员,您将看到预期的输出:

  fwrite(&record.x, sizeof record.x, 1, fp);
  fwrite(&record.y, sizeof record.y, 1, fp);
Run Code Online (Sandbox Code Playgroud)

PS:确保错误检查所有可能失败的功能(fopen,fwrite等).