【问题标题】:C - recursive function that accepts pointers as parameters problemC - 接受指针作为参数的递归函数问题
【发布时间】:2019-05-22 01:57:30
【问题描述】:

我遇到了一个问题,我必须编写一个接受两个参数的函数(都是指针,第一个指向数组的开头,第二个指向最后一个之后的内存位置数组元素)

函数必须从数组的第一个元素调用到中间的元素,然后从中间元素调用到末尾的元素,然后函数应该返回这两个元素中较大的值.

double max_element(double *p1, double *p2)
{
    double from_first_to_middle = max_element(p1, (p1 + p2) / 2 + p1);

    double from_middle_to_last = max_element((p1 + p2) / 2 + p1, p2);

    if(from_first_to_middle > from_middle_to_last)
    {
        return from_first_to_middle;
    }
    else
    {
        return from_middle_to_last;
    }
}

但是当我尝试运行这段代码时,它给了我错误

error: invalid operands to binary + (have ‘double *’ and ‘double *’)

然后我想我应该取消引用这些指针,因为我不能对它们指向的地址进行这些操作,但它仍然不起作用。

谁能帮忙?

谢谢!

【问题讨论】:

  • 指针上唯一有效的算术运算是减法,因为它可能会给出偏移量。任何其他操作都是没有意义的(并且是不允许的 - 请参阅port70.net/~nsz/c/c11/n1570.html#6.5.6p2)。您可以改为使用p1+(p2-p1)/2 之类的操作,因为这里的第二个加法操作数将具有整数类型 (ptrdiff_t)。
  • 能否请您重新制定您的规范和问题?不清楚你的意思是“函数必须从数组的第一个元素调用到中间的那个,然后从中间的元素到最后的那个,然后函数应该返回的值那两个更大的。”。另外,第二个指针指向数组中最后一个元素之后的东西?这对我来说听起来很危险。
  • @John:您通常必须使用此约定来简化算法,即p1 == p2 表示空,p1 + 1 == p2 表示单个项目,因此p2 - p1 产生 1 尽管p2 指向数组外部.除非你取消引用它,否则它不是 UB。
  • @Groo 当然,如果没有取消引用,一切都很好。但是你怎么能确定 p2 在数组中的最后一个元素之后呢?我不会再深入这个了。这个问题需要重构。
  • 不知道为什么这个问题被否决了。对我来说看起来不错。代码需要一些格式化。

标签: c function recursion


【解决方案1】:

指针不是整数。只为它们定义了几个算术运算,而指针+指针加法和指针/整数除法不在其中(它们是什么意思?)。您可以将整数添加到指针以获取另一个指针,该指针与原始指针偏移指定数量的目标对象。相反,您可以从另一个指针中减去一个指针以获得一个整数,该整数表示两个指向的目标对象的数量。这两种操作都有限制,但不应影响您需要执行的操作。

您可以将上述类型的指针算术运算与一些整数(仅)算术一起使用来计算函数所需的中点指针。细节留作练习。

【讨论】:

    【解决方案2】:

    也许这会有所帮助。

    double max_element(double *p1, double *p2)
    {
        double from_first_to_middle = max_element(p1, (double *)((size_t)(p2 - p1) / 2) + p1);
    
        double from_middle_to_last = max_element((double *)((size_t)(p2 - p1) / 2 + 1) + p1, p2);
    
        if (from_first_to_middle > from_middle_to_last)
        {
            return from_first_to_middle;
        }
        else
        {
            return from_middle_to_last;
        }
     }
    

    【讨论】:

    • max_element 正在等待 p\ointers。你为什么要通过size_t
    • @EugeneSh。我的错,已修复。
    • 不过,将ptrdiff_t 转换为size_t 看起来不是一个好主意。为什么你需要这个演员阵容?我想你可以摆脱所有的演员表。
    • 顺便说一句,看起来逻辑被打破了。您传递差异而不是指针。
    • @EugeneSh。 size_t 可以安全地表示指针类型。此外,我们有一个前提条件是 p2 大于 p1。请参阅viva64.com/en/a/0050 地址算术中 ptrdiff_t 和 size_t 类型的安全性部分
    【解决方案3】:

    我认为您的代码不会结束,因为您的返回有一些问题。 如果p1 + 1 == p2,则递归继续递归。你应该添加一行

    if ((p1+1) == p2)
     return *p1;
    

    一开始。

    double max_element(double* p1, double* p2){
        if ((p2 - p1) <= 0)
            exit(1);
        if ((p1+1)==p2)
            return *p1;
    }
    

    【讨论】:

      【解决方案4】:

      如果不使用p1p2,而是使用与from_first_to_middlefrom_middle_to_last 变量名称匹配的指针名称,事情可能会变得更清楚:

      double max_element(double *first, double *last)
      {
          if (last - first == 1)
          {
              return *first; // base case of our recursion
          }
      
          double *middle = first + (last - first) / 2;
      
          double from_first_to_middle = max_element(first, middle);
      
          double from_middle_to_last = max_element(middle, last);
      
          if (from_first_to_middle > from_middle_to_last)
          {
              return from_first_to_middle;
          }
      
          return from_middle_to_last;
      }
      

      虽然(p1 + p2) / 2p1 + (p2 - p1) / 2 是相同的常规数字,但由于缺少指针加法,该逻辑不适用于指针。即使这样,您的公式:(p1 + p2) / 2 + p1 对于常规数字也是错误的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-11
        • 2013-06-06
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 2020-06-07
        • 2017-11-28
        • 1970-01-01
        相关资源
        最近更新 更多