【问题标题】:Printing elements of a long array gives wrong output,打印长数组的元素会给出错误的输出,
【发布时间】:2015-09-07 06:51:39
【问题描述】:

我正在尝试编写一个函数,它接受列表大小和上限(用于随机数)并返回数组中的随机数。 这是我写的。

bool inList(long *heads, int num, int s){
    for (int i=0; i<s; i++){
        if (heads[i] == num){
            return true;
        }
    }
    return false;

}

long* generateRandomList(size_t s, int n){
    long heads[s];
    for (long i=0; i<s; i++){
        heads[i] = -1;
    }
    srand(time(NULL));
    for(int i=0; i<s; i++){
        int r;
        while (true){
            r = ( rand() % n ) + 1;

            bool isInList = inList(heads, r, s); // unique numbers

            if (isInList == false){
                break;
            }
        }
        heads[i] = r;
        printf("i %d r %d\n", i, r); // this is ok

    }
    return heads;
}



int main(){
    size_t s = 20;
    size_t n = 100;
    long *lists;
    lists = generateRandomList(s, n);

for (int i=0; i<s;i++){
      printf("%d, %d\n",i, lists[i] );
  }

}

generateRandomList() 中的第一个 printf 工作正常.. 但是,第二个会产生一些垃圾值.. 这是示例输出。

// from printf inside generateRandomList function
i 0 r 16
i 1 r 4
i 2 r 11
i 3 r 20
i 4 r 5
i 5 r 14
i 6 r 3
i 7 r 6
i 8 r 17
// from second printf.
0, 16
1, 16
2, -712138747
3, 1
4, 5
5, 14
6, 3
7, 6
8, 17

【问题讨论】:

  • 我很惊讶你可以编译这段代码。最后几行代码是否在所有函数之外?
  • @YuHao:已编辑..我刚刚剪掉了代码的相关部分..道歉。

标签: c arrays printf


【解决方案1】:

首先,我相信

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

应该阅读

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

这是 this 代码 sn-p 中的错字。


解决问题,在您的代码中,首先, heads 数组是函数 generateRandomList() 的本地数组。这就是为什么函数内部的第一个printf() 通过访问heads 数组会产生正确的输出。

一旦函数执行完毕,你return的局部变量的地址,返回后就失效了。因此,在调用者函数中访问返回的指针本质上是访问无效内存并调用undefined behaviour。这就是在第二次打印时打印出 garbage 值的原因。

解决方案:如果您需要 return 来自函数的指针并在调用者中使用它,则必须定义指针并使用动态内存分配 API 分配内存,例如 malloc() 和系列。

敲敲:也别忘了free()

接下来,对格式说明符使用错误类型的参数也会调用 UB。 %d 需要 int 类型的参数,但您在此处传递了 long

解决方案:long 需要有%ld 格式说明符和printf()

【讨论】:

  • @Sourov Ghosh.. 编辑头像以列出
  • @Fraz 现在我确信您在拼写正确时遇到了问题。 :P(我是苏拉夫)
  • 我已将 printf 类型更改为 ld.. 但仍然看到同样的问题
  • @Fraz 请阅读我更新的答案。不匹配的格式说明符不是代码中的唯一问题。
  • 是的,是的。 malloc 解决了这个问题。
【解决方案2】:

您正在使用动态数组,它没有明确的方式告诉您您可能没有足够的内存(在这种情况下是在堆栈上)。因此,您的程序有时可能会转储内核。

更重要的是,您从堆栈上不再存在的函数返回一个局部自动变量,这将被下一个函数调用覆盖。

避免使用动态数组,除非您知道堆栈大小足够。

如果您想返回一个持久数组,请使用 malloc() 而不是动态数组。

【讨论】:

    猜你喜欢
    • 2015-12-02
    • 1970-01-01
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    相关资源
    最近更新 更多