在函数中使用Structs

时间:2011-08-10 05:18:25

标签: c optimization

我有一个函数,我正在访问一个struct的成员很多次。 我想知道的是什么是好的做法?

例如:

struct s
{
    int x;
    int y;
}

我使用malloc为该结构的10个对象分配了内存。

因此,每当我只需要在函数中使用一个对象时,我通常创建(或作为参数传递)指针并将其指向所需的对象(我的上司告诉我要避免数组索引,因为它添加了访问结构的任何成员时的计算)

但这是正确的方法吗?我知道解除引用并不像创建副本那么昂贵,但如果我在函数中多次取消引用(如20到30)该怎么办。

如果为结构变量创建临时变量(只有我需要的变量,我当然不使用所有成员)并复制值然后在返回之前设置实际结构的值会不会更好?

另外,这是不必要的微优化吗?请注意,这适用于嵌入式设备。

4 个答案:

答案 0 :(得分:3)

这适用于嵌入式系统。所以,我不能对编译器的作用做任何假设。我无法对字大小,寄存器数量或访问堆栈的成本做出任何假设,因为您没有告诉我架构是什么。我曾经在8080年代做新的嵌入式代码......

好的,那该怎么办?

选择一段真实的代码并对其进行编码。按照上面列出的每种不同方式对其进行编码。编译它。找到强制它打印出生成的汇编代码的编译器选项。使用每组不同的优化选项编译每段代码。获取处理器的参考手册并计算每种情况使用的周期。

现在,您将拥有作为决策依据的真实数据。真实数据比一百万经验丰富的专家程序员的意见要好得多。与你的首席程序员坐下来向他展示代码和数据。他可能会向您展示更好的编码方式。如果是这样,按照他的方式重新编码,编译它,并计算他的代码使用的周期。告诉他他的方式如何成功。

在最糟糕的情况下,你将花一个周末来学习一些关于编译器工作方式非常重要的东西。您将检查N种方法来编码M次不同的优化选项集。您将学到很多关于机器指令集的知识。您将了解编译器的优缺点。您将有机会更好地了解您的首席程序员。而且,您将拥有真实的数据。

真实数据是您回答此问题时必须具备的数据类型。没有任何人告诉你的数据,除了基于自我的猜测。数据回答了这个问题。

鲍勃彭德尔顿

答案 1 :(得分:2)

首先,索引数组并不是非常昂贵(只有一个操作比指针取消引用更昂贵,或者有时没有,取决于具体情况)。

其次,大多数编译器在按值返回结构时将执行所谓的RVO或返回值优化。这是调用者为它调用的函数的返回值分配空间的地方,并秘密地将该内存的地址传递给它要使用的函数,结果是没有复制。它会自动执行此操作,所以

struct mystruct blah = func();

只构造一个对象,将其传递给func,使其对程序员透明地使用,不需要复制。

我不知道的是,如果为数组索引分配函数的返回值,如下所示:

someArray[0] = func();

编译器会传递someArray[0]的地址并以这种方式执行RVO,还是只是不进行优化?你必须得到一个更有经验的程序员来回答这个问题。我猜想编译器虽然很聪明,但它只是一个猜测。

是的,我称之为微优化。但我们是C程序员。并that's how we roll

答案 2 :(得分:1)

通常,您希望在C中复制传递的结构的情况是您要在适当的位置操作数据。也就是说,让您的更改不会反映在它自己的结构中,而只反映在返回值中。至于哪个更贵,它取决于很多东西。其中许多将实现改为实施,因此我需要更具体的信息才能更有帮助。虽然,我希望,在嵌入式环境中,你的内存比你的处理能力更高。实际上这看起来像不必要的微优化,你的编译器应该处理它。

答案 3 :(得分:0)

在这种情况下,在堆栈上创建临时变量会更快。但是如果你的结构要大得多,那么你可能会更好地解除引用。