【问题标题】:C Segmentation Fault from function that returns the maximum of an array来自返回数组最大值的函数的C分段错误
【发布时间】:2021-03-02 22:04:21
【问题描述】:

我只有一个函数可以找出整数数组的最大值,但我得到了一个 分段错误,因为编译器没有显示该行,所以我找不到它的错误。

这是我的 C 代码:

#include <stdlib.h>
#include <stdio.h>

//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int **arrayPointer){
    int max = 0;
    for (int i = 0; i < 3; i++) {
        if (*arrayPointer[i]>max) {
            max = *arrayPointer[i];
        }
    }
    return max;
}


int main (int argc, char **argv) {
    int array[4]={1,2,3,4};
    int *ptr = array;
    int z = groesstesElement(&ptr);
    printf("%d\n", z);

    return EXIT_SUCCESS;
}

我使用 macOS 和 VSC。

【问题讨论】:

  • 分段错误是运行时错误。编译器不会知道这些。
  • 调试器............
  • 问题的根源在于您无缘无故地使用指向指针的指针。这反过来又使您的代码变得不必要地复杂,并且您最终编写了一个优先级错误。

标签: arrays c segmentation-fault max


【解决方案1】:

在 C 中,数组索引 [] 的优先级高于指针取消引用 *https://en.cppreference.com/w/c/language/operator_precedence

一些括号修复了段错误。

if ((*arrayPointer)[i]>max) {
    max = (*arrayPointer)[i];
}

【讨论】:

  • @chrizzla 不,不是。还要检查我的答案。 (无论如何,这个答案简洁,准确,值得被接受)。
【解决方案2】:

由于运算符优先级,与

*arrayPointer[i]

你在告诉你的程序:

获取数组arrayPointer的第第i个元素并取消引用它。

但是arrayPointer 是一个指向int * 的指针,所以你得到的只是ptr 的地址(从main 定义的int ** 指针)带有一个偏移量。当您最终取消引用它时,您很可能访问了无效地址,从而导致分段错误。

正如主要答案已经建议的那样,修复是使用括号完成的,以便按照您想要的顺序应用运算符:

(*arrayPointer)[i]

代码中的次要问题

即使经过上述更正,程序不会再崩溃,但它不会工作。使用循环搜索数组

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

您不会在搜索中包含最后一项(索引 3),而会精确跳过在您的示例中包含最大值的索引。您的意思可能是for (i = 0; i &lt; 4; i++)for (i = 0; i &lt;= 3; i++)

无论如何,在代码中使用幻数(在本例中为数组的维度)被认为是不好的做法。更好的解决方案是使用#define,但更好的解决方案是将数组的大小传递给函数:

#include <stdlib.h>
#include <stdio.h>

#define ARR_SIZE 4

//Funktion ermittelt den größten Wert eines Arrays
int groesstesElement(int *arrayPointer, unsigned int arrSize){
    int max = 0, i;
    for (i = 0; i < arrSize; i++) {
        if (arrayPointer[i]>max) {
            max = arrayPointer[i];
        }
    }
    return max;
}


int main (int argc, char **argv) {
    int array[ARR_SIZE]={1,2,3,4};
    int z = groesstesElement(array, ARR_SIZE);
    printf("%d\n", z);

    return EXIT_SUCCESS;
}

请注意如何不再需要使用双指针

【讨论】:

  • 感谢您的详细回答。帮助我更好地了解我的代码中发生了什么。我实际上使用双指针只是为了习惯它们并了解它们是如何工作的。
猜你喜欢
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 2017-09-29
  • 1970-01-01
  • 2018-06-17
  • 2018-08-15
相关资源
最近更新 更多