Changing array inside function in C

前端 未结 7 1953
伪装坚强ぢ
伪装坚强ぢ 2020-12-01 08:40

I am learning C and confused why a array created in the main wont change inside the function, i am assuming the array passed is a pointer, and changing the pointer should\'v

相关标签:
7条回答
  • 2020-12-01 08:59

    Ok, i will make the answer short.

    1. Arrays are always passed by reference in C

    change(array, length); In this line, it means reference to the first element of the array variable is passed to the function.

    Now the function needs a pointer to catch the reference, it can be a pointer or it can be an array. Note that the pointer or the array is local to the function.

    1. You received it in a pointer named array. Which is definitely a pointer but it is not the same as array in main function. It is local to the change function.

    2. You declared a new array dynamically, and assigned a pointer named new with it. And all the changes you did were to new pointer.

    Everything is ok till now.

    1. Now you assigned the new pointer to the array pointer which is local to the change function.

    This is the real issue. As even though the array is in heap section, and it will remain in the memory, but the *array and *new are local pointer variables.

    Also array pointer in change function is different from array pointer in main function.

    1. The solution to this problem is Manipulate the data of array pointer directly.

      void change(int *array,int length) { int i; for(i = 0 ; i < length ; i++) array[i] = 1; }

    In this way you are directly overwriting values of array in main function. Everything else is correct.

    Summerization: array pointer in change function is local to change function. array in main function is local to main function. Making change function's local array pointer point to array in heap section won't change data in actual array. You changed pointer's position, Not the array's data.

    0 讨论(0)
  • 2020-12-01 09:06

    You pass a pointer to the array array to the function change. In this function you create another array called new (using new as a name is a bad idea) and then assign it to the locally created function parameter array. You do not modify pointer in your main function. If you would like to do so, you should use

    array = change(array,length);
    

    in your main function and

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

    in your change function.

    0 讨论(0)
  • 2020-12-01 09:07

    Your array in main is an array. It will decay to a pointer, to produce the behavior you expect, but it is not a pointer.

    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.
    

    What your code is doing is copying the address of a into a function-local variable. Modifying it will have no more difference outside than changing length.

    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);
    }
    

    If you wish to modify a pointer from the caller, you will need to use pointer-to-pointer syntax:

    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
    }
    

    However: There is a problem with what you are trying to do that goes deeper than this.

    In your code, "int a" is an array on the stack, not an allocated pointer; you cannot free it and you should avoid mixing heap/stack pointers this way because eventually you'll free the wrong thing.

    0 讨论(0)
  • 2020-12-01 09:19

    In c you can't pass a variable by reference, the array variable that you assign inside the function contains initially the same address as the passed pointer, but it's a copy of it so modifying it will not alter the passed pointer.

    You need to pass the address of the pointer in order to be able to alter it, like this

    // 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;
    }
    

    Then in main() you cannot assign to an array, doing so through this kind of function is surely undefined behavior. The array defined in main() is allocated on the stack and you cannot assign anything to an array since they are non-writeable lvalues so you cannot make it point to a heap memory location obtained with malloc(), you need to pass a pointer like this

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

    If you want the function to replace the previous array, it will have to free() the malloc()ed data (note that passing NULL to free() is well defined), so

    // 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;
    }
    

    then in main()

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

    will do what you apparently want.

    0 讨论(0)
  • 2020-12-01 09:21
                #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;
                }
    
    0 讨论(0)
  • 2020-12-01 09:23

    To use pass by value:
    Make the following change:
    In function change(...), replace:

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

    To:

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

    EDIT:
    But to use pass by reference:

    //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
                                       //
    }
    

    Then in main, make the following changes, and it will work as you purposed:

    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;
    }
    
    0 讨论(0)
提交回复
热议问题