【问题标题】:Static or Pointer When "Returning" Array“返回”数组时的静态或指针
【发布时间】:2018-05-22 19:56:02
【问题描述】:

我正在尝试使用随机值加载大小为 n(用户输入)的数组。我读过你不能在 C 中返回一个数组,你必须使用一个指针(这很令人困惑)。但是,我读到如果您将该数组存储到返回函数中的局部变量中,则指针将不起作用并且可以使用静态数组(可以在函数中返回吗?)。另外,我读到你应该在使用数组打开空间备份后调用free?我一定是用错了,因为它崩溃了。所以我暂时把它注释掉了。澄清一下就好了。

这是我目前所拥有的。打印时,它只是打印我认为只是垃圾的东西。

int* prefixAverages1(int);

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

int main() {

    int choice;
    int input;

    printf("What is the size of the array?:");
    scanf("%d", &input);
    printf("Do you want to run prefixAverages 1 or 2?");
    scanf("%d", &choice);

    switch(choice) {
        case 1:
            printf("Beginning prefixAverages1\n");
            int *a = prefixAverages1(input);
            for (int i=0; i < input; i++) {
                printf("%d", &i);
                printf("%d \n", a[i]);
            }
            //free(a);
            break;
    }
}

int* prefixAverages1(int input) {
    int x[input];
    int *a = (int*)malloc(input);
    srand(time(NULL));  

    for(int i = 0; i < input; i++) {
        int s = 0;
        for(int j = 0; j < i; j++) {
            int r = rand() % 100;
            x[j] = r;
            s = s + x[j];
        }
        a[i] = s / (i+1);
        printf("%d \n", a[i]);
    }
    return a;
}

我知道我的语法可能有问题。我已经很多年没有接触过 C 语言了,如果我的错误是语法错误,请告诉我。

edit:值按函数中的预期打印。在代码中添加了打印语句以提高清晰度

【问题讨论】:

  • 为什么不在 main() 中创建一个数组,然后将其发送给要修改的函数?
  • @AustinStephens 我已经想到了,但我最终需要将数组传递回主数组。这不会让我回到同样的境地吗?
  • 不,你发送的数组也会在main()中被修改;你不必返回任何东西。
  • @AustinStephens 我猜这就是指针功能发挥作用的地方?这听起来像是可行的,但我的任务明确要求将数组传回主目录。
  • printf("%d", &amp;i); == printf("%d: ", i);

标签: c arrays pointers static


【解决方案1】:

我正在尝试加载一个大小为 n 的数组(用户输入),随机 价值观。我读过你不能在 C 中返回一个数组,你必须使用 一个指针(这很令人困惑)。

是的,指针和数组之间的关系以及你不能用数组本身做的事情的范围非常广泛,这些都是常见的混淆点。在某种程度上,这是一种迂腐的区别。几乎所有 C 语言都允许您对数组进行操作,它使您可以通过指针进行操作,但它会自动将数组类型的值转换为适当的指针,因此这些细节在很大程度上被隐藏了。

但在某些地方它会突出。例如,没有有效的语法允许您尝试声明返回数组的函数。

在其他地方,它具有误导性。例如,您可以声明一个看起来接受数组作为参数的函数,但标准明确规定该参数实际上是一个对应的指针(当您调用这样的无论如何功能)。具体来说:

int foo(int x[3]);

100% 等价于

int foo(int *x);

但是,我已经读过,如果你 将该数组存储到返回函数中的局部变量中, 指针不起作用

这不是专门针对数组,而是关于一般的自动变量。当它们超出范围时(在声明它们的最内层块的末尾),这些逻辑上不再存在,因此一旦函数返回,指向或指向此类对象的指针不再有效。获得这种指针值的一种方法是让函数返回它。这本身没问题,但你不能安全地取消引用这样的指针值。

并且可以使用静态数组(可以是 在函数中返回?)。

任何类型的静态变量的生命周期都是程序的整个执行过程。因此,从函数返回指向静态变量的指针 (in) 是安全且有意义的。但是虽然它可以从你的函数返回一个指向静态数组的指针,但你仍然不能返回这样一个数组本身。

另外,我听说你应该 使用数组后调用free是否打开空间备份?

您应该释放您使用内存分配函数之一(malloc() 等)分配的内存,而不是其他。但是,当您在函数内部分配内存时,您可以通过返回指向它的指针等方式让调用者负责释放该内存。

事实上,您在示例代码中演示的大部分内容在这些方面都很好。但是,您确实犯了一个破坏程序的关键错误。这里:

    int *a = (int*)malloc(input);

您分配input 字节 并将指向它们的指针存储在a 中,但这对于input 类型int 的对象来说是不够的。 int 的大小因实现而异,但标准允许的最小大小是两个字节,最常见的大小是四个字节。要为int 类型的input 对象分配空间,基本习惯用法是

int *a = malloc(input * sizeof(int));

不过,我个人更喜欢

int *a = malloc(input * sizeof(*a));

因为无论指针的引用类型是什么类型,即使我稍后更改它,我都会得到正确的大小。

您将分配的空间视为比实际更大的事实可能解释了您的程序的大部分不当行为,包括您尝试释放分配的内存时崩溃。

【讨论】:

  • 这很有意义!感谢您浏览我的每一个问题并单独回答。
【解决方案2】:

首先malloc 需要一个字节数而不是绝对数组大小的参数 - 所以改变这一行:-

int *a = (int*)malloc(input);

int *a = malloc(input*sizeof(int));

其次,要调试正在打印的不正确值,请在您的函数中打印一个 prefixAverages1 :-

...
...
a[i] = s / (i+1);
printf("%d \n", a[i]);
...

在主打印中,去掉第一个打印..这可能会让你认为打印不正确的值..本地循环计数器变量的地址看起来像垃圾

printf("%d", &i);

或者,如果您想跟踪数组元素的索引并将其修改为:-

printf("%d", i);

你必须将free引入后面以避免内存泄漏

你应该遵循@AustinStephens 的建议,避免使用第二个函数

【讨论】:

  • 谢谢。我不确定我是否正确使用了malloc。更改后,我仍然在主页面中打印不正确的值。
  • 函数中的值打印正确。仅在返回主目录时。
【解决方案3】:

只要有一个函数可以加载带有随机值的数组:

void randomValues(int arr[], int size);

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

int main() {
    int i;
    int input;
    int *array;

    printf("What is the size of the array?: ");
    scanf("%d", &input);

    array = malloc(sizeof(int) * input);

    randomValues(array, input);

    for(i = 0; i < input; ++i)
        printf("array[%d] = %d\n", i, array[i]);

    free(array);

    return 0;
}

void randomValues(int arr[], int size) {
    int i;
    int r;

    srand((int) time(0));

    for(i = 0; i < size; ++i) {
        r = rand() % 100;
        arr[i] = r;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2019-01-24
    • 2022-11-21
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    相关资源
    最近更新 更多