在C中更改函数内部的数组

时间:2016-01-17 21:35:16

标签: c arrays function pointers

我正在学习C并且困惑为什么在main中创建的数组不会在函数内部发生变化,我假设传递的数组是一个指针,并且更改指针应该更改数组,对吧?有人能解释一下这种情况会发生什么吗?

这是帮助。

Before:0 10 20 30 40 50 60 70 80 90 
After:1 1 1 1 1 1 1 1 1 1 

我希望看到以下输出:

Before:0 10 20 30 40 50 60 70 80 90 
After:0 10 20 30 40 50 60 70 80 90 

我得到了什么:

{{1}}

8 个答案:

答案 0 :(得分:8)

中,您无法通过引用传递变量,您在函数内分配的array变量最初包含与传递的指针相同的地址,但它是' sa它的副本,所以修改它不会改变传递的指针。

你需要传递指针的地址才能改变它,就像这个

一样
// Change the pointer of the array
void change(int **array, int length)
{
    *array = malloc(length * sizeof(int));
    if (*array == NULL)
        return;
    for (int i = 0 ; i < length ; i++)
        (*array)[i] = 1;
}

然后在main()中你不能分配给一个数组,通过这种函数这样做肯定是未定义的行为。 main()中定义的数组在堆栈上分配,您无法为数组分配任何内容,因为它们是 -writeable lvalues ,因此您无法指向它使用malloc()获取的堆内存位置,您需要传递一个像这样的指针

int *array;
change(&array, length);
free(array);

如果您希望该函数替换以前的数组,则必须free() malloc()个数据(请注意,将NULL传递给free()是定义明确),所以

// Change the pointer of the array
void change(int **array, int length)
{
    free(*array);

    *array = malloc(length * sizeof(int));
    if (*array == NULL)
        return;
    for (int i = 0 ; i < length ; i++)
        (*array)[i] = 1;
}

然后在main()

int *array;
array = NULL;
change(&array, length);
change(&array, length);
change(&array, length);
change(&array, length);
free(array);

会做你想要的。

答案 1 :(得分:1)

一个简单的例子:

#include <stdio.h>

void print_array(const int arr[], const int n){
    int i;
    for(i=0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

void change_array(int arr[]){
    arr[0] = 239;
    arr[1] = 234234;
}

int main(){
    int arr[10] = {};
    print_array(arr,10);
    change_array(arr);
    print_array(arr,10);
    return 0;
}
输出:
0 0 0 0 0 0 0 0 0 0 
239 234234 0 0 0 0 0 0 0 0

答案 2 :(得分:0)

将指向数组array的指针传递给函数change。在此函数中,您创建另一个名为new的数组(使用new作为名称是一个坏主意),然后将其分配给本地创建的函数参数array 。您修改main功能中的指针。如果您愿意,请使用

array = change(array,length);

在你的主要功能和

int *change(int *array, int length) {
    int *variable_called_new =(int *)malloc(length*sizeof(int));
    [...]
    return variable_called_new
}

change函数中。

答案 3 :(得分:0)

使用按值传递
进行以下更改:
在函数change(...)中,替换:

int i;for(i=0;i<length;i++)new[i] = 1;

要:

int i;for(i=0;i<length;i++)array[i] = 1;
                           ^^^^^

修改的:
但是要使用按引用传递

//To change the contents of a variable via a function call
//the address of that variable has to be passed. So, if you
//want to change the contents of an array of int, i.e. int *array, you 
//need to pass its address, not the variable itself,  using the 
//address of operator, it would look like this &array (read _the address of
// pointer to int "array")
//This requires you to change the prototype of your function:
void change2(int **a, int len)
{
    int i;
    for(i=0;i<len;i++) (*a)[i] = 1;//parenthesis bind * to a to assure 
                                   //array of pointers to int ( *[] )is populated
                                   //
}

然后在main中,进行以下更改,它将按照您的目的运行:

int main(){
    int i,length=10;
    int *array;

    array = calloc(length, sizeof(int));
    if(!array) return 0;
    //or malloc if preferred.  But note, in C, 
    //casting the output is not required on either.
    //array = malloc(length*sizeof(int));
    //if(!array) return 0;

    for(i=0;i<length;i++)array[i]=i*10;

    printf("Before:");print(array,length);
    change2(&array,length);
    printf("After:");print(array,length);

    free(array);

    return 0;
}

答案 4 :(得分:0)

main中的数组是数组。它将衰减为指针,以产生您期望的行为,但它不是指针。

int a[10];
int* p = a; // equivalent to &a[0]; create a pointer to the first element
a = p;      // illegal, a is NOT a pointer.

您的代码正在做的是将a的地址复制到函数局部变量中。修改它与改变长度之外没有其他区别。

void change(int* local_ptr, size_t length)
{
    local_ptr = 0;
    length = 0;
}

int main()
{
    int a[10];
    int length = 10;
    printf("before a=%p, length=%d\n", a, length);
    change(a, length);  // we copied 'a' into 'local_ptr'. 
    printf("after a=%p, length=%d\n", a, length);
}

如果你想修改来自调用者的指针,你需要使用指针到指针的语法:

void change(int** ptr, size_t length)
{
    // change the first element:
    **ptr = 0;
    // change the pointer:
    *ptr = 0;
    // but ptr itself is a function-local variable
    ptr = 0;  // local effect
}

但是:你想要做的事情有一个问题比这更深入。

在你的代码中,&#34; int a&#34;是堆栈上的数组,而不是分配的指针;你不能释放它,你应该避免以这种方式混合堆/堆栈指针,因为最终你会解除错误的东西。

答案 5 :(得分:0)

所以当你传递数组时,你会得到它的开头地址:

内存 地址

| -junk- | 1000

| --- 0 --- | 1008&lt; - 数组的开始

| --- 10-- | 1012

。 。   。

当你在函数中得到指针时,它的值是1008(例子),所以改变它只会意味着你现在指向另一个地方。那不是你想要的。 你可以通过*运算符直接改变指向的整数,所以 *array = 99;将更改第一个元素, *(array+1) = 98;第二个等等。 你也可以更自然地使用[]运算符。 所以在你的功能  array[0] = 99;实际上会更改原始数组。

答案 6 :(得分:0)

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

            // Print on console the array of int
            void print(int *array,int length)
            {
                int i;
                for(i = 0 ; i < length ; i++)
                    printf("%d ", array[i]);
                printf("\n");
            }

            // Change the pointer of the array
            void change(int **array,int length)
            {
                int i;
                int *ar;
                ar = (int *)malloc(sizeof(int *) * length);
                for(i = 0 ; i < length ; i++)
                    ar[i] = 1;
                (*array) = ar;
            }

            int main(){
                int i, length = 10;
                int *array;
                array = (int *)malloc(sizeof(int *) * length);

                for (i = 0 ; i < length ; i++)
                    array[i] = i * 10;
                printf("Before:");
                print(array, length);
                change(&array, length);
                printf("After:");
                print(array, length);

                return 0;
            }

答案 7 :(得分:0)

好的,我将回答简短。

  1. 数组总是通过引用在C中传递

change(array,length);   在此行中,这意味着将对数组变量的第一个元素的引用传递给函数。

现在函数需要一个指针来捕获引用,它可以是指针,也可以是数组。请注意,指针或数组在函数的本地。

  1. 您在名为array的指针中收到了它。绝对是一个指针,但它与main函数中的数组不同。它是更改功能的本地功能。

  2. 您动态声明了一个新数组,并为其分配了一个名为new的指针。而您所做的所有更改都是针对新指针。

到目前为止一切都还可以。

  1. 现在,您将新指针分配给了更改函数本地的数组指针。

这是真正的问题。就像数组在堆部分一样,它将保留在内存中,但是* array和* new是局部指针变量。

change函数中的数组指针也与main函数中的数组指针不同。

  1. 此问题的解决方案是 直接处理数组指针的数据。

    无效更改(int *数组,int长度) {     我     for(i = 0; i <长度; i ++)         array [i] = 1; }

这样,您可以直接覆盖main函数中的array值。其他一切都是正确的。

摘要: 更改函数中的数组指针是更改函数的局部指针。 主函数中的数组是主函数的局部数组。 使更改函数的本地数组指针指向堆部分中的数组不会更改实际数组中的数据。您更改了指针的位置,而不是数组的数据。