【问题标题】:Dynamic memory allocation for array passed as reference in C recursive function [closed]在C递归函数中作为引用传递的数组的动态内存分配[关闭]
【发布时间】:2014-04-13 16:44:52
【问题描述】:

我想计算我的递归嵌套了多少,并返回函数内部创建的数组中的每个级别编号,但该代码无法正常工作(运行时显示“分段错误”):

void test (int* result[], int* counter) {


  if (*counter == 0)
        *result = (int**) malloc(0);

    if (*counter == 5)
        return;

    else {
        *counter = *counter + 1;
        *result = (int**) realloc(*result, sizeof(int) * (*counter));
        *result[*counter - 1] = *counter; // This line is wrong, and I don't know why.
        test(result, counter);
    }
}

void main () {
    int** result;
    int counter = 0;

    test(result, &counter);

    int i;
    for (i = 0; i < 5; i++)
        printf("%d\n", *result[i]);
}

我知道我可以使用单指针作为参数和返回值来做到这一点。关键是,我只是好奇。

【问题讨论】:

  • “无法正常工作”不是有用的描述。请说明您观察到的行为以及您的预期。
  • 另外,不要添加多余的演员表(例如 malloc 的返回)。只在需要正确程序的地方强制转换,永远不要关闭编译器。使用-Wall -Wextra 向编译器询问所有警告,并适当地处理它们。 *result 不是 int** 顺便说一句。
  • 为了你好,试着用-Wall编译你的代码作为一种习惯:它会到处显示你所有的小错误;例如使用int** 作为int* 值的转换; main 缺少整数返回(以及 main 的错误原型),或初始化的 result 变量。关于那个,malloc 它是值得的,因为它可以在代码的当前状态下随机出现段错误;并按照-Wall 的建议更正它(例如,拥有int** result = NULL;)会告诉你它有段错误,但不是随机的,所以你可以更正它;)
  • 即使是偶然使用malloc(0)也是个坏主意;通过明确地编写它来做到这一点是一个非常糟糕的主意。您无法取消引用可靠返回的任何指针。

标签: c memory dynamic recursion allocation


【解决方案1】:

test() 的代码在我看来表面上没问题(我没有测试过,所以我不能肯定),但在 main() 中这是错误的:

for (i = 0; i < 5; i++)
    printf("%d\n", *result[i]);
}

你想要(*result)[i]。数组索引比指针解引用具有更高的优先级。

你也不应该强制转换malloc() 的返回值(参见Do I cast the result of malloc?),尤其是因为你做错了:*result 的类型是 int *,所以如果你想保留这个转换,在至少将其更改为int *,但我建议完全取消它。

更新:

这一行也是如此:

*result[*counter - 1] = *counter;

应该是:

(*result)[*counter - 1] = *counter;

【讨论】:

  • +1 用于指出数组索引运算符相对于指针取消引用的优先级。但这也是 test 函数 else 块的第三行失败的原因。这值得一提,因为这是 OP 提出的问题......
  • @7heo.tk 哦,对了。没看懂,谢谢指点。更新了我的答案。
  • Anytime ;) - 现在 OP 的代码可以编译并做他想做的事了。
【解决方案2】:

所有有问题或错误的行的简要说明:

*result = (int**) malloc(0);

该行要么将*result 设置为0,要么设置为某个必须为freed 的唯一值。此外,演员表是多余的并且是错误的,因为*result 的类型为int*。

*counter = *counter + 1;

上面对标准增量运算符大喊大叫:++*counter;

*result = (int**) realloc(*result, sizeof(int) * (*counter));

除了上面malloc标识的类型和转换问题,最好这样写以避免使用错误的大小:*result = realloc(*result,*counter * sizeof *result);

*result[*counter - 1] = *counter; // This line is wrong, and I don't know why.

运算符优先级表示需要加括号:(*result)[*counter - 1] = *counter;

void main () {

main 的唯一祝福原型是 int main(void) 和 int main(int argc, char* argv[argc]) 或兼容的。实现也可能允许其他人,尽管它们是不可移植的。

int** result;

x 你想要一个int* 在这里,因为你想用它作为test 的引用参数。

test(result, &counter);

注释x表示需要取上面result的地址。

for (i = 0; i < 5; i++)

您可能会考虑使用 *counter 作为通用性的限制,但在您的情况下,test 实际上总是将其设置为 5。

printf("%d\n", *result[i]);

如评论 x 所说,删除取消引用以获得良好结果。

【讨论】:

  • *counter++ 与 *counter = *counter+1; 不同。等价的形式是(*counter)++,或++*counter(严格来说,第二个是唯一的等价语句)。您想增加指向的对象,而不是指针。是的,*result[*counter - 1] = *counter; 行有问题 - 再次,一个优先问题:它应该是 (*result)[*counter - 1] = *counter;,因为动态数组位于 *result。
  • @FilipeGonçalves 我讨厌愚弄运算符优先级。很好的收获。
  • 哦,你并不孤单——我也是!现在我可以投票了 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 2015-01-10
  • 2017-10-28
  • 2018-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多