有没有更好的方法可以遍历指针而不将其重新分配给其他变量?

时间:2020-08-20 16:26:43

标签: c

struct hello1 {
    int64_t world1;
    int64_t world2;
    int64_t world3;
    int64_t world4;
    int64_t world5;
}

void something (struct hello1 *first) {

    int64_t *foo1 = &first->world1;

    for (int64_t i = 0; i < 0x30; i++) {
        printf("Address: 0xllx", foo1);
        foo1++;
    }
}

我当前正在将地址&first->wordl1分配给* foo1。

有没有一种更好的方法可以在不创建int64_t *foo1的情况下递增到结构中的下一个指针?

3 个答案:

答案 0 :(得分:3)

尝试通过指针算法从任何其他成员访问struct的任何成员的行为是未定义

更详细地讲,C标准允许您读取指针值&world1(并对其取消引用)和指针值&world1 + 1(但将其延迟) 。但是它不允许您读取指针值&world1 + 2及以上。

请考虑改用int64_t数组。然后指针算术将是有效的,并且您将不需要这些额外的强制转换。

如果您仍然坚持使用hello1,并且希望能够通过索引访问成员,请考虑

inline int64_t* getHello1Element(struct hello1* h, size_t i)
{
    switch (i){
    case 0:
        return &h->world1;
    case 1:
        return &h->world2;
    case 2:
        return &h->world3;
    case 3:
        return &h->world4;
    case 4:
        return &h->world5;
    }
}

它将是具有良好编译器的O(1)。

答案 1 :(得分:0)

您可以直接将.groupBy(x => x._1)添加到i

&first->world1

请注意,这将调用未定义的行为,因为它将使生成的指针超出范围。

还请注意,struct hello1 { int64_t world1; int64_t world2; int64_t world3; int64_t world4; int64_t world5; } void something (struct hello1 *first) { for (int64_t i = 0; i < 0x30; i++) { printf("Address: 0xllx", &first->world1 + i); } } 本身不会导致未定义的行为:格式中没有printf(),并且允许在%中使用多余的参数。 (多余的参数将被评估并忽略)

printf()在典型环境中不会导致任何结果,因此让我们删除这种无用的未定义行为。
&first->world1 + i也适合0x30(保证最多可以存储int),因此,32767仅使用int而不是int64_t
这是一种更好的方法:

i

答案 2 :(得分:0)

这是经典方式:

struct hello1 {
    int64_t world[5];
}

void something (struct hello1 *first) {
    for (int i = 0; i < 5; i++) {
        printf("Address: %p\n", first->world + i);
    }
}
void something_else(struct hello1 *first) {
    int64_t *foo = first->world;
    for (int i = 0; i < 5; i++) {
        printf("Address: %p\n", foo++);
    }
}

或者如果您想变得好玩:

struct hello1 {
    union {
       int64_t world[1];
       int64_t world1;
    };
    int64_t world2, world3, world4, world5;
}

但是它具有更可疑的价值,除非您必须使用单独的访问器来支持大量遗留物。