对 unsigned int 执行算术运算后出现分段错误

Getting segmentation fault after performing arithmetic on unsigned int

代码如下。我遇到分段错误不明白为什么。我认为这是因为我对变量 t 和 k(都是 unsigned int)做的算术运算,谁能解释为什么会出现这个分段错误。

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

int main() {

    unsigned int n,k,q,i,t;
    scanf("%u %u %u",&n,&k,&q);
    unsigned int a[n];
    for(i=0;i<n;i++)
    {
        scanf("%u",&a[i]);
    }
    for(i=0;i<q;i++)
    {
        scanf("%u",&t);
        if(t-k>0)
            printf("%u\n",a[t-k]);
        else
            printf("%u\n",a[t-k+n]);
    }   
    return 0;
}

我认为问题与这个 if 语句有关

    if(t-k>0)
        printf("%u\n",a[t-k]);

因为 tk 都是无符号整数,所以 t-k 的结果总是非负的,即使 t 小于 k .但是结果可以给数组元素a[t-k]

一个wong索引

else 语句

    else
        printf("%u\n",a[t-k+n]);

仅在 t 等于 k 时执行:) 但在这种情况下,数组 t-k+n 的索引将等于 n 并引用数组后面.

printf("%u\n",a[t-k+n]);

考虑到 if 语句中的条件

if(t-k>0)

可以代替

if ( t > k )

但是无论如何你应该检查输出元素的结果索引是否有效。

由于代码很小,这可能是开始使用 gdb 的好机会。这样,您可以节省很多时间。这是一个 introductory tutorial.


问题出在这里:

if(t-k>0) // <- HERE!
  printf("%u\n",a[t-k]);
else
  printf("%u\n",a[t-k+n]);

因为 tk 是无符号整数。这些变量的某些值将暴露问题。例如,我在 if-else 语句之前添加了一个 printf(),我得到:

2
2
2
1
2
1
RESULT: -1
Segmentation fault (core dumped)

所以,你可以看到,因为变量是无符号整数,所以t-k的结果是always非-负数,作为无符号整数运算的结果,无论 tk 的值是什么。

作为解决方案,您可以将这两个变量设置为整数,如下所示:

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

int main() {

    unsigned int n,q,i;
    int t,k;
    scanf("%u %d %u",&n,&k,&q);
    unsigned int a[n];
    for(i=0;i<n;i++)
    {
        scanf("%u",&a[i]);
    }
    for(i=0;i<q;i++)
    {
        scanf("%d",&t);
        printf("RESULT: %d\n", t-k);
        if(t-k>0)
            printf("%u\n",a[t-k]);
        else
            printf("%u\n",a[t-k+n]);
    }   
    return 0;
}

现在输出变为:

2
2
2
1
2
1
RESULT: -1
2

可以看到,这里没有出现分段错误,并且按预期打印了 2。