gpt4 book ai didi

c 链表,offsetof 返回值不允许强制转换回父结构地址

转载 作者:行者123 更新时间:2023-11-30 17:35:34 25 4
gpt4 key购买 nike

相关文章: [c 循环双链表:rev 遍历为同一节点提供不同的列表指针地址](c circular double linked-list: rev traverse gives different list-pointer address for same node)

使用嵌入数据结构中的通用列表结构实现循环双链表[上述相关帖子中的解决方案(3)]我遇到了一个问题,其中offsetof(struct ,member) 返回错误的偏移量。这会阻止使用该解决方案。我知道报告的偏移量可能取决于编译器,但我需要知道如何处理编译器给出的任何结果。 full source is this link 。下面显示了列表实现和收到的不正确的 offsetof 值。我不知道为什么返回的offsefof值不是实际需要的值。例如,在下面的代码中,offsetof (DataA,node) 报告偏移量(无符号长整型)为 24,但需要值 80?

typedef struct Node {
struct Node *prev, *next;
} Node;

typedef struct DataA {
int i;
char c;
double d;
char *a;
Node *node;
} DataA;

void
showlistA (Node *list, int manoff)
{
if (list == NULL) {
fprintf (stdout,"%s(), The list is empty\n",__func__);
return;
}

Node *iter = list;

do {
int offset = (int)offsetof (DataA, node);
DataA *offsetaddr = (DataA*)((unsigned long)iter - (unsigned long)offset);
printf ("node: %p, offsetof(DataA,node): %d, result: %p,\n\t\t\t \
need offset: %d, need result: %p\n\n",
iter, offset, offsetaddr, manoff, (DataA*)((unsigned long)iter - manoff));

iter = iter-> next;
} while (iter != list);
}

int
main(int argc, char *argv[])
{

Node *list = NULL;
int manoffset = 80;

if (argc < 2)
fprintf(stderr, "\nNote: Usage: %s (int) (offsetof(DataA,node)) (default: 80)\n", argv[0]);

manoffset = (argv[1]) ? atoi (argv[1]) : 80;

printf ("\ncreate_node_Ann()\n");
create_node_Ann (&list, 1, 'A', 1000.101, "my dog has fleas");
create_node_Ann (&list, 2, 'B', 2000.101, "my cat has more");
create_node_Ann (&list, 3, 'C', 3000.101, "my snake has none");
create_node_Ann (&list, 4, 'D', 4000.101, "my hamster is fine");

printf ("\nNumber of nodes in 'list': %d\n\n", get_list_sz (list));

printf ("Node pointers (list validation):\n");
showlistptrs (list);
printf ("\n");
printf ("Offsets (reported/required):\n");
showlistA (list, manoffset);

/* Output is compiler dependent - reported results */
printf ("Offsets reported for each member of DataA:\n");
printf (" offsets: i=%ld; c=%ld; d=%ld; a=%ld; node=%ld\n",
(long) offsetof(struct DataA, i),
(long) offsetof(struct DataA, c),
(long) offsetof(struct DataA, d),
(long) offsetof(struct DataA, a),
(long) offsetof(struct DataA, node));
printf (" sizeof(struct DataA)=%ld\n\n", (long) sizeof(struct DataA));

exit(EXIT_SUCCESS);
}

显示返回值的偏移量以及列表信息的输出是:

create_node_Ann()
1 DataA ndata : 0x603010
ndata-> node : 0x603060
2 DataA ndata : 0x603080
ndata-> node : 0x6030d0
3 DataA ndata : 0x6030f0
ndata-> node : 0x603140
4 DataA ndata : 0x603160
ndata-> node : 0x6031b0

Number of nodes in 'list': 4

Node pointers (list validation)
1 prev: 0x6031b0 cur: 0x603060 next: 0x6030d0
2 prev: 0x603060 cur: 0x6030d0 next: 0x603140
3 prev: 0x6030d0 cur: 0x603140 next: 0x6031b0
4 prev: 0x603140 cur: 0x6031b0 next: 0x603060

Offsets (reported/required):
node: 0x603060, offsetof(DataA,node): 24, result: 0x603048,
need offset: 80, need result: 0x603010

node: 0x6030d0, offsetof(DataA,node): 24, result: 0x6030b8,
need offset: 80, need result: 0x603080

node: 0x603140, offsetof(DataA,node): 24, result: 0x603128,
need offset: 80, need result: 0x6030f0

node: 0x6031b0, offsetof(DataA,node): 24, result: 0x603198,
need offset: 80, need result: 0x603160

Offsets reported for each member of DataA:
offsets: i=0; c=4; d=8; a=16; node=24
sizeof(struct DataA)=32

我不明白为什么 offsetof 值与所需的值如此不同。为什么 DataA *p = (DataA*)((uintptr_t)iter - offsetof(DataA, node)); 返回 24 而不是 80 ?完整的程序采用单个参数(偏移量)并将其应用为手动偏移量,以允许输入列表节点和 DataA 结构地址之间的正确转换。 (这就是我测试实际需要的内容以及我的计算器的方式)。我该如何解决这个问题?

最佳答案

问题出在 DataA 的定义中,其中节点定义为指针而不是 @molbdnilo 指出的结构。 struct DataA 的正确定义是:

typedef struct DataA {
int i;
char c;
double d;
char *a;
Node node;
} DataA;

将节点重新定义为结构体而不是指向结构体的指针后,offsetof 值是正确的。感谢大家的帮助。

关于c 链表,offsetof 返回值不允许强制转换回父结构地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22978298/

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