为什么 C 使用 5 个字节来 write/fwrite 数字 10,而用 4 个字节来写 9 或 11?

Why does C use 5 bytes to write/fwrite the number 10, but 4 bytes to write 9 or 11?

海湾合作委员会 Windows

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

struct test {
    int n1;
    int n2;
};

int main() {
    FILE *f;
    
    f = fopen("test.dat", "w");
    struct test test1 = {10, 10};
    fwrite(&test1, sizeof(struct test), 1, f);
    fclose(f);
    
    struct test test2;
    f = fopen("test.dat", "r");
    while(fread(&test2, sizeof(struct test), 1, f))
        printf("n1=%d n2=%d\n", test2.n1, test2.n2);
    fclose(f);
    
    return 0;
}

如果我将 test1 设置为 10,10,那么 fwrite 将写入 10 个字节 到文件:0D 0A 00 00 00 0D 0A 00 00 00

(每个 4 字节的 int 将在其前面填充一个 0D 回车 return 字符)

如果我将 test1 设置为 11,11,那么 fwrite 将写入 8 个字节 到文件:0B 00 00 00 0B 00 00 00

(如我所料)

如果我将 test1 设置为 9,9,那么 fwrite 将写入 8 个字节 到文件:09 00 00 00 09 00 00 00

(如我所料)

如果我将 test1 设置为 9,10 那么 fwrite 将写入 9 个字节 到文件:09 00 00 00 0D 0A 00 00 00

9 按预期获得 4 个字节,但 10 被额外填充 0D 字节,结果为 5 个字节。需要此填充的数字 10 有何特别之处?为什么较小和较大的数字(8、9、11、12、13、14 等)都没有被填充?我想也许 GCC 混淆了换行符的数字 10(换行符是 10 是 acsii),但这并不能解释 fread 如何正确地得到数字 10。

以及如何在不对数字 10 进行额外填充的情况下将结构写入文件?

您正在以文本模式写作和阅读。

打开带有标志“wb”和“rb”的文件。这会将文件视为二进制文件。

您在 text 模式下打开文件,因此 Windows 每个 '\n' 字符前面都有一个回车符 return .

您应该改为 binary 模式写入(和读取)二进制数据 (fopen(..., "wb")) -- 这样会更快,并且避免意外(并且还需要只有 8 个字节,这就是 sizeof(struct test)

What is so special about the number 10 that requires this padding?

数字10恰好是换行符('\n')的ASCII码。