-3

所以我有这两个结构。只需要担心这三个变量;name_size、name 和 xattrs[0]。

typedef struct dxattr {
    unsigned int name_size;        /* length of name string in bytes */
    unsigned int value_offset;     /* offset of value in value blocks */
    unsigned int value_size;       /* length of value string in bytes */
    char name[0];                  /* reference to the name string */
} dxattr_t;

typedef struct xcb {
    unsigned int value_blocks[5];  /* blocks for xattr values */
    unsigned int no_xattrs;            /* the number of xattrs in the block */
    unsigned int size;                 /* this is the end of the value list in bytes */
    dxattr_t xattrs[0];                /* then a list of xattr structs (names and value refs) */
} xcb_t;

首先我更新 xattrs 中的索引 0

xcb_t *xcb = (xcb_t*)malloc( sizeof(xcb_t) );

xcb->xattrs[0].name_size = 5;

memcpy( xcb->xattrs[ 0 ].name, "keith", 5 );
xcb->xattrs[ 0 ].name[ 5 ] = 0; //null terminator

printf("xcb->xattrs[0].name = %s\n", xcb->xattrs[0].name );
printf("xcb->xattrs[0].name_size = %d\n", xcb->xattrs[0].name_size );

输出是;

xcb->xattrs[0].name = keith                                                                                             
xcb->xattrs[0].name_size = 5 

然后我尝试更新第二个索引。

memcpy( xcb->xattrs[ 1 ].name, "david", 5 );
xcb->xattrs[ 1 ].name[ 5 ] = 0; //null terminator

printf("xcb->xattrs[0].name = %s\n", xcb->xattrs[0].name );

xcb->xattrs[1].name_size = 5;

printf("xcb->xattrs[0].name = %s\n", xcb->xattrs[0].name );

更新“name_size”变量后,先前索引中的“name”值立即被删除。

xcb->xattrs[0].name = keith                                                                                             
xcb->xattrs[0].name = 

知道为什么会这样吗?

4

2 回答 2

1

您可以为 xattrs 的数量和 xattrs 中名称的大小分配足够的内存。当只有 1 个由[ ]或指示的不确定数组大小时,[ 0 ]它并不那么困难,但是在有多个维度的情况下,这是非常痛苦的。

实际上,您不能将 xattrs 成员用作数组来索引高于 1 的索引。由您编写字节地址计算代码来根据名称字段的大小确定 xattrs 的第二个实例的地址第一个实例,然后如果有第三个 xattrs 实例,则再次执行所有这些工作。

如果你不能简单地声明一个非常大的缓冲区并一口气读完,并且你坚持保留这个结构,那么你能做的最好的事情就是:

keep a note of total size
malloc the minimum size => total size (as you have done)
read only the minimum size
for the number of attrs
    next totalsize+= 1 minimum xattr
    realloc for next total size
    generate an xattr pointer based on the current total size
    read the minimal attr to that pointer
    next totalsize+= name size
    realloc for next total size
    generate an xattr pointer based on the current total size
    read the name
    current = next size

这些类型的数据结构有时用于描述磁盘上的二进制文件,或通过 RPC 传输的 blob,作为示意图。但在现实中它们实际上并不容易操纵。

另请注意,在某些平台上(包括 x86,如果您启用了 sse 优化),您将遇到这些数据结构的 int 成员的对齐问题。

如果您只是想将此结构从磁盘流式传输到内存中,请声明一个使用指针的新数据结构 - 指向名称的指针和指向 attr 的指针数组或指向 attr 的指针数组的指针,这样你可以根据需要 malloc 每一件事并构建一个等效的数据结构。

于 2019-12-05T18:55:04.257 回答
1

正如我从您的代码中了解到的那样,您正在尝试“破解结构”。为此,最好使用 C11 的一个标准特性,称为“灵活数组成员”。语法是这样的:

typedef struct dxattr {
    unsigned int name_size;        /* length of name string in bytes */
    unsigned int value_offset;     /* offset of value in value blocks */
    unsigned int value_size;       /* length of value string in bytes */
    char name[ ];                  /* reference to the name string */
} dxattr_t;

typedef struct xcb {
    unsigned int value_blocks[5];  /* blocks for xattr values */
    unsigned int no_xattrs;            /* the number of xattrs in the block */
    unsigned int size;                 /* this is the end of the value list in bytes */
    dxattr_t xattrs[ ];                /* then a list of xattr structs (names and value refs) */
} xcb_t;

请注意,最后一个成员数组被声明为没有常量大小 0,因为它是不完整的类型。我是 Stack Overflow 的新手,所以也许你的问题更深层次,我的共享知识可能还不够。

于 2019-12-05T18:26:49.677 回答