如何将值从第一个数组复制到另一个数组?

时间:2018-12-02 11:06:49

标签: c arrays

所以,我有一个包含1个值的数组。然后我将其复制(分配)到另一个数组。但是,如果我更改第二个数组的值,那么第一个数组的值也将更改。这是我的代码:

#include <stdio.h>

void change(int a[]){
    int *temp = a;
    for(int i=0; i<2; i++){
        a[i] = temp[0]*10+7;
    }
    //What I expect for the result is a[0] = 7, a[1] = 7 instead of a[0] = 7, a[1] = 77
}
int main(){
    int num[1];
    num[0] = 0;
    change(num);
    printf("%d", num[0]);
    return 0;
}

我的阵列怎么了?

EDIT :我要复制值,而不是数组地址

编辑2 :我在上面的代码中做了一些更改,以使我更清楚自己想要的内容。

6 个答案:

答案 0 :(得分:4)

“但是,如果我更改第二个数组的值,那么第一个数组的值也会更改”

数组作为副本传递(数组不按值传递)-它是指向第一个元素在内存中的地址的指针。因此,您实际上是在修改值(通过引用传递的数组)

请注意!当将数组作为参数传递时:

RedissonClient redissonClient = RedissonClient.create(config); RKeys keys = redissonClient.getKeys(); // default batch size on each SCAN invocation is 10 for (String key: keys.getKeys()) { ... } // default batch size on each SCAN invocation is 250 for (String key: keys.getKeys(250)) { ... }

表示完全相同:

void func(int a[])

答案 1 :(得分:0)

在c数组中通过引用传递。这意味着您不是传递值,而是传递数组元素存储的地址。

在函数中将值分配给a [0]时,实际上是在更新num数组。

答案 2 :(得分:0)

当仅使用数组名称传递给函数时,实际上是创建一个指向数组第一个元素的临时指针。因此,您的change()函数将main中的num []数组的地址作为该临时指针的副本接收。

整个概念称为“参考传递”。

答案 3 :(得分:0)

如果要将数组的副本传递给C中的函数,则可以将数组放入结构中,并按值传递此结构,例如

struct s {
  int a[4];
};

void change(struct s elem)
{
   elem.a[0] = 1; //assigment to copy
}

答案 4 :(得分:0)

首先,此声明

void change(int a[]);

等同于此声明

void change(int *a);

第二(有关更多信息,请参见this link

  

C语言毫无例外地传递值。传递指针   作为参数并不意味着通过引用。

因此,您正在传递指针地址的副本(指向相同的数组/地址)。然后,您只需取消引用数组的第一个位置并为其分配一个值(这实际上只是指针算法)。

也许有助于重写代码以使指针的算术更加明显:

#include <stdio.h>

void change(int *a){
    int temp[1];
    *(temp+0) = *(a+0);
    *(a+0) = *(temp+0) * 10 + 7;
}

int main(){
    int num[1];
    *(num+0) = 0;
    change(num);
    printf("%d", *(num+0));
    return 0;
}

我不确定如何理解 EDIT

  

EDIT :我要复制值,而不是数组地址

看着代码,我无法理解您可能想要尝试实现的目标。请对此进行澄清。

在阅读您的说明后,我了解到您不想在main函数中修改数组元素,而在change函数中修改数组元素。

答案是您不能这样做。解释如上所述。我建议您花一些时间来学习C语言中的指针算术和数组。在这方面,K&R书籍确实很棒。我真的很推荐这本书。

您可以做的是将数组的内容复制到另一个数组中,然后修改该数组;例如在该函数的开头或在调用该函数并将该复制的数组作为参数传递之前。

答案 5 :(得分:0)

如果要在函数内部创建数组副本,以便可以在不更改原始数组的情况下处理数组副本,最好的选择是自己创建数组的显式副本。

最简便的方法是使用malloc()calloc()分配内存,然后将原始数组的内容复制到新的内存分配中。如果选择此路径,则您的代码必须确保在不再需要任何动态分配的内存时释放它们。可以通过循环并使用数组索引符号访问分配的内存,或使用memcopy()复制原始数组的内容来完成复制。另一种选择是使用可变长度数组(在C99中添加到C中,在C11和C17中是可选的,但仍得到广泛支持),以避免自己动态分配和取消分配内存。

这是一个示例程序,其中包含两个函数work_on_copy()work_on_copy_vla(),每个函数采用一个数组,将其复制,并执行一些更改副本的工作。最后一个参数提供一个数组索引,该索引用于说明在函数内部完成工作后如何使用数组副本有选择地修改原始数组。如果此参数是有效的数组索引,则该索引处的值将从数组副本复制到原始数组。

请注意,也可以通过将数组包装在struct中来解决此问题,但是此方法的缺点是要求该struct的数组成员的大小必须与最大数组的大小相同这是预料之中的,在一般情况下会浪费内存。

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

void print_array(size_t arr_sz, int arr[]);
void work_on_copy(size_t arr_sz, int arr[], int index);
void work_on_copy_vla(size_t arr_sz, int arr[], int index);

int main(void)
{
    int my_arr[] = { 1, 2, 3, 4 };
    size_t my_arr_sz = sizeof my_arr / sizeof *my_arr;

    puts("-- Do not change original array at all --");
    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);

    work_on_copy(my_arr_sz, my_arr, -1);

    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);

    work_on_copy_vla(my_arr_sz, my_arr, -1);

    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);
    putchar('\n');

    puts("-- Change specified index of original array after work --");
    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);

    work_on_copy(my_arr_sz, my_arr, 1);

    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);

    work_on_copy_vla(my_arr_sz, my_arr, 3);

    printf("Array in main(): ");
    print_array(my_arr_sz, my_arr);

    return 0;
}

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

void work_on_copy(size_t arr_sz, int arr[], int index)
{
    /* make copy of array: could return a pointer to this allocation */
    int *arr_copy = malloc(sizeof *arr_copy * arr_sz);

    /* handle error if allocation fails */
    if (arr_copy == NULL) {
        perror("unable to allocate memory");
        return;
    }
    memcpy(arr_copy, arr, sizeof *arr_copy * arr_sz);  // or use a loop

    /* do work on local copy */
    for (size_t i = 0; i < arr_sz; i++) {
        arr_copy[i] += 10;
    }

    printf("Array copy after work (malloc): ");
    print_array(arr_sz, arr_copy);

    /* update original array if needed */
    if (index >= 0 && (size_t)index < arr_sz) {
        arr[index] = arr_copy[index];
    }

    /* deallocate memory to avoid memory leaks */
    free(arr_copy);
}

void work_on_copy_vla(size_t arr_sz, int arr[arr_sz], int index)
{
    /* make local copy of array using a VLA */
    int arr_copy[arr_sz];
    for (size_t i = 0; i < arr_sz; i++) {
        arr_copy[i] = arr[i];
    }

    /* do work on local copy */
    for (size_t i = 0; i < arr_sz; i++) {
        arr_copy[i] *= 2;
    }

    printf("Array copy after work (VLA): ");
    print_array(arr_sz, arr_copy);

    /* update original array if needed */
    if (index >= 0 && (size_t)index < arr_sz) {
        arr[index] = arr_copy[index];
    }
}

程序输出:

-- Do not change original array at all --
Array in main(): 1 2 3 4 
Array copy after work (malloc): 11 12 13 14 
Array in main(): 1 2 3 4 
Array copy after work (VLA): 2 4 6 8 
Array in main(): 1 2 3 4 

-- Change specified index of original array after work --
Array in main(): 1 2 3 4 
Array copy after work (malloc): 11 12 13 14 
Array in main(): 1 12 3 4 
Array copy after work (VLA): 2 24 6 8 
Array in main(): 1 12 3 8