【问题标题】:Returning multiple values from a C function从 C 函数返回多个值
【发布时间】:2009-07-06 18:49:51
【问题描述】:

重要提示:请参阅这个非常相关的问题:Return multiple values in C++

我在寻找如何在 ANSI C 中做同样的事情?你会使用结构体还是传递函数中参数的地址?我追求极其高效(快速)的代码(时间和空间),即使以可读性为代价。

编辑:感谢所有答案。好吧,我想我应该解释一下:我正在写这本书,内容是针对特定领域的某个算法子集。我为自己设定了一个相当武断的目标,即为我所有的算法在网络上提供最有效的(时间和空间)实现,但以牺牲可读性和其他东西为代价。这部分是我(一般)问题的性质。

答案:我希望我能直截了当,从(可能)最快到更符合常识(所有这些都是先验的,即未经测试):

  1. 将 outvalues 存储在全局对象中(我会假设类似 outvals[2]?),或者
  2. 将输出值作为参数传递给函数 (foo(int in, int *out1, int *out2)),或者
  3. 返回一个包含两个值的结构,或者
  4. (3) 仅当值在语义上相关时。

这有意义吗?如果是这样,我认为 Jason 的回应是最接近的,尽管它们都提供了一些“谜题”。罗伯特的很好,但此时语义不是我所追求的(尽管他的建议得到了适当的注意)

谢谢大家。

【问题讨论】:

  • 无情地编写您的代码和配置文件。我想您会发现 struct-vs-reference 的性能影响与您的其他实现相比如此微不足道,甚至不值得考虑。
  • 这也是个好建议。谢谢。 (顺便说一句,我确实对你投了赞成票,碰巧我正在寻求一个更实际的答案,仅此而已。)
  • 在 C 中,使用“foo(int in, int &out1, int &out2)”的“答案 2”表示法没有意义 - 引用是在 C++ 中,而不是 C。
  • 通常,一本书会受益于将清晰度作为首要目标,将空间和时间表现作为次要目标。你如何处理空间和时间之间的紧张关系——最节省空间的算法往往不是最节省时间的?如果你已经有两种算法,为什么不也提出一个清晰、简单、可靠的算法呢? (对 3 个选择的一个答案是因为选择太多。)
  • @Jonathan。评论 1) 已修复,谢谢。评论 2) 我并不是要粗鲁,但我并不是真的在寻求关于如何写论文或书籍的建议。没有写过长篇专着的人给出的建议通常倾向于“写你自己的小说”书籍给出的建议:“了解你的听众,保持清醒,晚上坐下来阅读”。 . 对于某些人来说,这些只是空洞的老生常谈。

标签: c data-structures


【解决方案1】:

当然,这两种方式都有效,但我会考虑语义(结构与参数引用)来决定哪种方式最好地将您的意图传达给程序员。

如果您返回的值紧密耦合,则可以将它们作为结构返回。但是,如果您只是创建 人工机制 以一起返回值(作为结构),那么您应该使用参数引用(即传递变量的地址)将值返回给调用函数。

【讨论】:

    【解决方案2】:

    正如尼尔所说,您需要自己判断。

    为了避免传递任何东西的成本,请使用全局变量。下一个最好的是通过指针/引用传递的单个结构。之后是单独的指针/引用参数。

    但是,如果您必须将数据打包到结构中,然后在调用后将其读回,则最好传递单独的参数。

    如果您不确定,只需使用这两种方法编写一些快速测试代码,每个方法执行几十万次,然后为它们计时,看看哪种方法最好。

    【讨论】:

      【解决方案3】:

      您已经描述了两种可能的解决方案以及您认为的性能限制。您从这里到哪里去真的取决于您 - 我们没有足够的信息来做出明智的判断。

      【讨论】:

      • 我明白了。刚开始C,想知道是否有更好的方法。你会说结构比替代方案更昂贵吗?
      • 致编辑 - 更正时请确保自己的拼写。
      • @Dervin 这两个选项之间的性能可能没有太大差异,但这取决于您如何使用结构等,我们没有详细信息。如果性能如此重要(坦率地说,它很少如此重要),那么您必须执行自己的测量以找出最快的。
      • GMan,感谢教科书上的建议,但在我职业生涯的这个阶段,我可以向你保证,我可以同时担心这两个问题。 :)
      【解决方案4】:

      最容易阅读的应该是函数中传递的地址,而且速度也应该很快,弹出和推送很便宜:

      void somefunction (int inval1, int inval2, int *outval1, int *outval2) {
         int x = inval1;
         int y = inval2;
      // do some processing
         *outval1 = x;
         *outval2 = y;
         return;
      }
      

      【讨论】:

      • 你的意思是 &outval1, int &outval2?
      【解决方案5】:

      我能想到的最快的问答方式是在全局对象上传递值,这样你就可以跳过堆栈操作,只是记住它不是线程安全的。

      【讨论】:

      • 不一定,如果需要将全局对象提取到缓存中。
      【解决方案6】:

      我认为当您返回一个结构指针时,您可能需要为此手动查找一些内存。参数列表中的地址在堆栈上分配,这样更快。

      【讨论】:

        【解决方案7】:

        请记住,有时通过值传递参数并在返回时更新(或在堆栈上制作本地副本)比通过引用更快...这对于小型结构或少量参数和大量访问非常明显。

        【讨论】:

          【解决方案8】:

          这在很大程度上取决于您的架构,以及您是否期望(或可以拥有)内联函数。我会先以最简单的方式编写代码,然后担心速度是否会成为代码中昂贵的部分。

          【讨论】:

            【解决方案9】:

            我会将地址传递给结构。如果要返回的信息并不复杂,那么只需将地址传递给值也可以。

            就个人而言,这真的归结为界面的混乱程度。

            void SomeFunction( ReturnStruct* myReturnVals )
            {
              // Fill in the values
            }   
            
            // Do some stuff    
            ReturnStruct returnVals;
            SomeFunction( &returnVals);    
            // Do more stuff
            

            【讨论】:

            • 原谅我的无知,我还不太懂C。为什么返回结构的本地副本不好?
            • 实际上,如果您没有指向函数内分配的内存,那也不错。我只是要删除该块以减少混乱。
            • @Soo Wei Tan - 不,你对函数内分配的内存是正确的(这很糟糕) - 你不需要删除它,这是关于训练以正确的方式。
            • 我很高兴他删除了它。从 C 中的函数返回结构并没有什么不好。它实际上引起了混乱。
            【解决方案10】:

            在任何一种情况下,您都在传递引用,因此性能应该相似。如果函数有可能从未真正返回值,则可以使用“返回结构”选项避免 malloc 的成本,因为您只需返回 null。

            我个人的偏好是返回一个动态分配(malloc'd)的结构。我避免在输出中使用函数参数,因为我认为从长远来看这会使代码更加混乱且难以维护。

            【讨论】:

            • 动态分配至少意味着内存泄漏的可能性。这意味着您的函数的用户必须更加小心。
            【解决方案11】:

            返回结构的本地副本是不好的,因为如果结构在函数内被声明为非静态,一旦退出函数,它就会变为 null 和 void。

            对于所有建议参考的人,OP 确实说“C”,而 C 没有它们(参考)。

            还有可爱的羽毛耶稣,我明天醒来可以不用在电视上看到任何关于翻牌之王的事情吗?

            【讨论】:

              猜你喜欢
              • 2022-04-29
              • 1970-01-01
              • 2018-01-01
              • 2021-12-21
              • 2017-12-24
              • 1970-01-01
              相关资源
              最近更新 更多