【问题标题】:Getting segmentation fault after performing arithmetic on unsigned int对 unsigned int 执行算术后出现分段错误
【发布时间】:2015-08-17 09:59:59
【问题描述】:

代码如下。我得到分段错误无法理解为什么。我认为这是因为我对变量 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(t-k&gt;0)...提示:未签名的操作。考虑 t = 1, k = 2....
  • 谢谢@SouravGhosh,知道了。
  • 这显示了正确使用编译器警告的重要性。启用大量警告,它应该会告诉您将unsigned 与零进行比较。
  • @TobySpeight, gcc -Wall -pedantic px.c 没有发出相对警告。我应该使用哪个标志?
  • @gsamaras 我认为-Wall -Wextra 可能就足够了,但我承认没有对此进行测试。所以我可能需要修改我的评论——如果你测试了t-k&gt;=0,它会警告你,因为a[0+n]超出了范围。

标签: c segmentation-fault unsigned-integer integer-arithmetic


【解决方案1】:

我认为问题与这个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 )

但在任何情况下,您都应该检查输出元素的结果索引是否有效。

【讨论】:

  • else 语句也无效,因为当t = k 然后a[t-k+n] 变为a[n] 时超出a 的范围。
  • 你想要t&gt;=k在条件中。
  • @Toby Speight 我写了一个对应于条件 t - k > 0 的条件,前提是它是有效的。
  • @VladfromMoscow 你的回答让我看起来太差了,这是我的+1。你认为我应该删除它吗?
  • @gsamaras 您应该添加一个检查结果索引在您的演示程序中是否有效。
【解决方案2】:

由于代码很小,这可能是开始使用 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 的结果总是非负数,这是对无符号数进行操作的结果整数,无论​​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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多