gpt4 book ai didi

c - fread() : Reading from a file (without alignment) results in skipping of bytes

转载 作者:行者123 更新时间:2023-12-04 00:55:12 24 4
gpt4 key购买 nike

我有一个文件并使用 C 我想使用 fread() (来自 stdio.h)读取它的内容并将其写入结构的成员中。 (在我的情况下,开头有一个 2 字节的 int,后跟一个 4 字节的 int。)
但是在将文件内容正确写入结构体的前两个字节变量后,它会跳过两个字节,然后继续处理第二个四字节变量。
为了演示,我创建了一个 16 字节的文件来读取。在十六进制中它看起来像这样(小端):22 11 66 55 44 33 11 11 00 00 00 00 00 00 00 00使用以下代码,我期望第一个变量 twobytes , 为 0x1122第二个,fourbytes , 为 0x33445566 .但它打印:

twobytes: 0x1122 
fourbytes: 0x11113344

sizeof(FOO) = 8
&foo : 0061FF14
&foo.two : 0061FF14
&foo.four: 0061FF18
跳过字节 3 和 4 ( 0x66 & 0x55 )。代码:
#include <stdio.h>
#include <stdint.h>

int main(void) {

FILE* file = fopen("216543110.txt", "r");
if (file==NULL) { return 1; }

typedef struct
{
uint16_t twobytes;
uint32_t fourbytes;
}__attribute__((__packed__)) // removing this attribute or just the underscores around packed does not change the outcome
FOO;

FOO foo;

fread(&foo, sizeof(FOO), 1, file);

printf("twobytes: 0x%x \n", foo.twobytes);
printf("fourbytes: 0x%x \n\n", foo.fourbytes);

printf("sizeof(FOO) = %d\n", sizeof(FOO));
printf("&foo : %p\n", &foo);
printf("&foo.two : %p\n", &foo.twobytes);
printf("&foo.four: %p\n", &foo.fourbytes);

fclose(file);
return 0;
}
使用具有两个相同大小整数的结构按预期工作。

所以:使用 fread() 写入不同大小的变量会导致跳过字节:
22 11 .. .. 44 33 11 11 ...代替
22 11 66 55 44 33 ...
我知道有关字节对齐的某些内容在这里起作用,但这如何影响字节的读取?如果 C 想要向结构添加填充,这对从文件中读取有什么影响?
我不在乎 C 是否将结构成员存储为
22 11 .. .. 66 55 44 33 ...或者
22 11 66 55 44 33 ... ,
我很困惑为什么它无法正确读取我的文件。
另外,我正在使用 gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)

最佳答案

从你的程序产生的输出来看,编译器似乎忽略了 __attribute__(__packed__)规范。
gcc online user's guide文档 __attribute__ ((__packed__)) type 属性与示例,其中此属性放置在 { 之前的定义。
此扩展是非标准的,因此不同的编译器或任何给定编译器的不同版本可能会根据放置选择不同地处理它。如果您使用 gcc,移动属性应该可以解决问题。如果您使用不同的编译器,请查看文档以了解它的不同之处。
还要注意这些注释:

  • 该文件应以二进制模式打开,使用 "rb" ,
  • sizeof(FOO)参数应该被转换为 (int)%d转换说明符。
  • %p 的指针参数应该被转换为 (void *) .
  • foo.twobytesfoo 的地址相同,这是 C 标准和 &foo.fourbytes 强制要求的位于 4 个字节之外,这意味着 foo.fourbytes对齐并且两个成员之间有 2 个填充字节。

  • 尝试以这种方式修改您的代码:
    #include <stdio.h>
    #include <stdint.h>

    int main(void) {
    FILE *file = fopen("216543110.txt", "rb");
    if (file == NULL) {
    return 1;
    }

    typedef struct __attribute__((__packed__)) {
    uint16_t twobytes;
    uint32_t fourbytes;
    } FOO;

    FOO foo;

    if (fread(&foo, sizeof(FOO), 1, file) == 1) {
    printf("twobytes : 0x%x\n", foo.twobytes);
    printf("fourbytes: 0x%x\n\n", foo.fourbytes);

    printf("sizeof(FOO) = %d\n", (int)sizeof(FOO));
    printf("&foo : %p\n", (void *)&foo);
    printf("&foo.two : %p\n", (void *)&foo.twobytes);
    printf("&foo.four: %p\n", (void *)&foo.fourbytes);
    }
    fclose(file);
    return 0;
    }

    关于c - fread() : Reading from a file (without alignment) results in skipping of bytes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63053490/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com