fwrite() 如果任何单个字节的符号位为 1,则将全 1 写入更高有效位(写入 int)

fwrite() writing all 1's to more significant bits if sign bit of any single byte is 1 (writing int)

for (struct part *p = first; p != NULL; p = p->next;) {
    fwrite(&(p->num), sizeof(int), 1, inventory);
    fwrite(&(p->qoh), sizeof(int), 1, inventory);
    fwrite(p->name, sizeof(char), strlen(p->name) + 1, inventory);
}

p 是指向结构实例的指针,如下所示:

struct part{
    int num;
    int qoh;
    char *name;
    struct part *next;
};

如果我将数字 8、104、3176 等存储在 num 中,一切都很好。但是,如果我存储 128、32768 或任何使用字节最高有效位的数字(字节为 1XXX-XXX 的任何数字),fwrite 会将所有 1 写入文件中所有更重要的字节,将 128 转换为-128、199 到 -57 等

这种字节更改不会在程序执行期间发生 - 仅在保存到文件时发生。查看 num = 199 和 qoh = 3,写入文件后,字节是这样的:

ff ff ff c7 00 00 00 03

应该是

00 00 00 c7 00 00 00 03

我将文件加载到清单程序中,它按预期加载了字节。 num = -57,不是 199。

我是不是用错了fwrite?

这是存储部分,应要求。

void part_new(void) {
    struct part *new;
    int num, qoh;
    char *name;

    printf("\nEnter a part number: ");
    scanf("%d", &num);
    while(getchar() != '\n');

    for (struct part *p = first; p != NULL; p = p->next) {
        if (p->num == num) {
            printf("Duplicate part number, name: %s. Canceling action.\n", p->name);
            return;
        }
    }
    printf("Enter a name: ");
    if ((name = input(PART_NAME_MAX_CHARS)) == NULL) {
        printf("Bad input.\n");
        return;
    }
    printf("Enter a QOH: ");
    scanf("%d", &qoh);
    while(getchar() != '\n');

    new = malloc(sizeof(struct part));
    new->num = num;
    new->qoh = qoh;
    new->name = malloc(strlen(name) + 1);
    strncpy(new->name, name, strlen(name) + 1);
    free(name);
    part_into_list(new);

    return;
}

和保存功能:

    bool save_file(char *fname) {
    FILE *inventory;
    struct part *del;

    if ((inventory = fopen(fname, "wb")) == NULL) {
        printf("\nCould not save %s.\n", fname);
        return false;
    }

    fseek(inventory, 0 , SEEK_SET);
    for (struct part *p = first; p != NULL; p = p->next) {
        fwrite(&(p->num), sizeof(int), 1, inventory);
        fwrite(&(p->qoh), sizeof(int), 1, inventory);
        fwrite(p->name, sizeof(char), strlen(p->name) + 1, inventory);
    }

    printf("%s saved.\n", fname);
    fclose(inventory);
    return true;
}

Am I using fwrite wrong?

不,你正在正确使用它。因此,结果的问题与您正在写入的数据或您正在写入的流有关。

考虑这个根据您的原始代码示例改编的完整程序:

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

struct part{
    int num;
    int qoh;
    char *name;
    struct part *next;
};

int main(void) {
    struct part sp = { 199, 3, "Foo" };
    FILE *fp = fopen("out", "wb");

    for (struct part *p = &sp; p != NULL; p = p->next) {
        fwrite(&(p->num), sizeof(int), 1, fp);
        fwrite(&(p->qoh), sizeof(int), 1, fp);
        fwrite(p->name, sizeof(char), strlen(p->name) + 1, fp);
    }

    fclose(fp);

    return 0;
}

将是一个合理的 MCVE,除了它实际上并没有为我重现错误这一事实。这是结果输出的十六进制转储:

c7 00 00 00 03 00 00 00 46 6f 6f 00

从这里您可以看到我的机器对其 int 使用小端表示法,而且它不会产生您所描述的损坏的整数。

回答了你的基本问题后,我不想整理你相对大量的代码来找出问题出现的位置和方式。然而,我仍然建议将其简化为 MCVE,因为这很有可能帮助您自己发现问题的本质,或者至少是其中涉及的关键陈述。