为什么 fwrite 为 uint8_t 写入两个字节?
Why does fwrite write two bytes for an uint8_t?
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);
}
出于某种原因,我最终得到:
$ hexdump -C example.bin
00000000 01 00 02 00 |....|
00000004
我期待:01 02 00
。
这是我的 c 编译器的版本,以防与 hardware/compiler 相关。
$ cc --version
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
结构通常由编译器填充 - 在 x
之后插入空 space,以便 y
与 16 位边界对齐。
GCC 提供 __attribute__((packed))
来禁用此行为;见 these docs
I am trying to write 3 bytes to file, but end up with 4.
您可能旨在写入 3 个字节,但实际上正在写入 sizeof(struct a)
,这很可能是 4,因为编译器插入了一个填充字节以进行对齐。也许您假设结构的大小等于其成员大小的总和,并且没有考虑可能的填充。
一般来说,编译器可以自由地以对齐方式插入填充(除非在结构的第一个成员之前不能有任何填充)。
如果您编写单个成员,您会看到预期的输出:
fwrite(&record.x, sizeof record.x, 1, fp);
fwrite(&record.y, sizeof record.y, 1, fp);
P.S.: 确保错误检查所有可能失败的函数(fopen、fwrite 等)。
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);
}
出于某种原因,我最终得到:
$ hexdump -C example.bin
00000000 01 00 02 00 |....|
00000004
我期待:01 02 00
。
这是我的 c 编译器的版本,以防与 hardware/compiler 相关。
$ cc --version
Apple LLVM version 9.1.0 (clang-902.0.39.1)
Target: x86_64-apple-darwin17.5.0
Thread model: posix
结构通常由编译器填充 - 在 x
之后插入空 space,以便 y
与 16 位边界对齐。
GCC 提供 __attribute__((packed))
来禁用此行为;见 these docs
I am trying to write 3 bytes to file, but end up with 4.
您可能旨在写入 3 个字节,但实际上正在写入 sizeof(struct a)
,这很可能是 4,因为编译器插入了一个填充字节以进行对齐。也许您假设结构的大小等于其成员大小的总和,并且没有考虑可能的填充。
一般来说,编译器可以自由地以对齐方式插入填充(除非在结构的第一个成员之前不能有任何填充)。
如果您编写单个成员,您会看到预期的输出:
fwrite(&record.x, sizeof record.x, 1, fp);
fwrite(&record.y, sizeof record.y, 1, fp);
P.S.: 确保错误检查所有可能失败的函数(fopen、fwrite 等)。