为什么这段代码会给某些输入带来分段错误?

时间:2015-07-01 22:38:46

标签: c segmentation-fault

//difference of two diagonals of a N x N matrix
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

int main() {

    int N, j, i,k,l;
    scanf("%d",&N);
    int array[N-1][N-1], sum1=0, sum2=0, sum=0;
    for(i=0;i<N; i++)
        {
        for(j=0; j<N; j++)
            {
            scanf("%d",&array[i][j]);
        }
    }
    for(k = 0; k<N; k++){
        sum1 += array[k][k];
    }
    for(l=0; l<N; l++){
        sum2 += array[N-1-l][l];
    }
    sum = abs(sum1 - sum2);
    printf("%d",sum);   
    return 0;
}

以上代码会为某些输入生成分段错误。程序计算两个主对角线中所有值的总和之间的绝对差值。

3 个答案:

答案 0 :(得分:1)

我认为,主要问题是您要声明大小为N - 1×N的数组,然后填写N元素。请尝试声明N×select t.*, (select p.price from pricing p where p.product = t.product and p.quantity >= t.quantity order by p.quantity limit 1 ) as price from transaction t;

答案 1 :(得分:1)

您将数组array声明为包含N-1行和N-1

int array[N-1][N-1], /*...*/;

因此,数组的行和列的索引的有效范围是[0, N-2]

但是在程序的循环中,您尝试使用索引N-1访问数组的元素。例如

for(i=0;i<N; i++)
    {
    for(j=0; j<N; j++)
        {
        scanf("%d",&array[i][j]);
    }
}

您正在尝试访问数组之外​​的内存,因此程序具有未定义的行为。

只需编写数组的声明,如

int array[N][N], /*...*/;

考虑到数组的大小应为正值。

您也可以删除标题

#include <string.h>
#include <math.h>

因为程序中没有使用标题声明。

答案 2 :(得分:0)

首先,无效输入会导致未定义的行为。

您需要确保输入有效,因为您可以检查scanf()的返回值,如下所示

if (scanf("%d", &N) != 1)
    return -1;

然后你需要确保N > 0,因为你为N - 1项目分配了空间,所以

if (N <= 1) /* this also prevents `int array[0][0];' */
    return -1;

应该添加。

然后你必须修复你的循环,你为N - 1项目分配空间,但你从N0进行N - 1次迭代,N - 1是一个无效索引如果您只分配了N - 1元素,则需要执行以下两项操作之一

  1. 修复循环

    for (int i = 0 ; i < N - 1 ; ++i) /* ... etc. */
    
  2. N元素分配空间

    int array[N][N];
    

    在这种情况下,您应该将N上的检查更改为

    if (N < 1)
        return -1;
    
  3. 不同输入触发不同行为的原因是因为访问超出其限制的数组会导致未定义的行为。所以它有时会工作一段时间会导致分段错误,甚至其他时候也会产生其他问题,因为它未定义

    但还有另一个未定义的行为来源,它还取决于输入,它与你使用scanf()的方式有关。如果您键入asdasd,那么当您声明N变量时,array将被取消初始化,因此也会发生未定义的行为。