1

假设我有一个这样的结构:

typedef struct {
    char *str;
    int len;
} INS;

以及该结构的数组。

INS *ins[N] = { &item, &item, ... }

当我尝试访问它的元素时,不是作为指针,而是作为结构本身,所有字段都被复制到一个临时的本地位置?

for (int i = 0; i < N; i++) {
    INS in = *ins[i];
    // internaly the above line would be like:
    // in.str = ins[i]->str;
    // in.len = ins[i]->len;
}

?

那么当我增加结构字段时,这将是一个更昂贵的分配操作?

4

4 回答 4

2

正确,in副本*ins[i]

不要介意你的内存消耗,但你的代码很可能不正确:对象in在循环体结束时死亡,你所做的任何更改in都不会产生持久的影响!

于 2012-08-14T15:02:57.767 回答
1

结构赋值的行为类似于memcpy. 是的,更大的结构更昂贵。矛盾的是,您的结构变得越大,就越难以衡量添加另一个字段的额外费用。

于 2012-08-14T15:05:58.127 回答
1

是的,结构value semantics在 C 中具有。因此,将结构分配给另一个结构将导致按成员复制。请记住,指针仍将指向相同的对象。

于 2012-08-14T15:06:32.817 回答
1

编译器可能会优化掉结构的副本,而是直接从数组访问成员以提供使用副本的 C 代码中所需的值,或者可能只复制您使用的单个成员。一个好的编译器会做到这一点。

通过指针存储值可能会干扰这种优化。例如,假设您的例程还有一个指向 int, 的指针p。当编译器处理你的代码INS in = *ins[i]时,它可能会“思考”这样的事情:“复制ins[i]是昂贵的。取而代之的是,我会记住那in是一个副本,稍后我会为它获取成员,当他们使用时。” 但是,如果您的代码包含*p = 3,这可能会改变ins[i],除非编译器能够推断出p不指向ins[i]. restrict(有一种方法可以帮助编译器使用关键字进行推断。)

总结:表面上看起来很昂贵的操作可能由一个好的编译器有效地实现。看起来便宜的操作可能很昂贵(写入会*p破坏大的优化)。通常,您应该编写清楚地表达您的算法的代码并让编译器进行优化。

扩展编译器如何优化它。假设你写:

for (int i = 0; i < N; i++) {
    INS in = *ins[i];
    ...
}

其中“...”中的代码访问 in.str 和 in.len,但不访问您添加到 INS 结构的其他 237 个成员中的任何一个。然后编译器可以自由地将这段代码转换为:

for (int i = 0; i < N; i++) {
    char *str = *ins[i].str; 
    int len = *ins[i].len;
    ...
}

也就是说,即使您编写了一个语句,表面上复制了所有 INS 结构,但编译器只需要复制实际需要的部分。(实际上,甚至不需要复制那些部分。只需要生成一个程序,获得与直接遵循源代码相同的结果即可。

于 2012-08-14T15:52:52.767 回答