数组作为函数入参传递,在函数内修改数据,原数据是否会被修改?

是的,在C语言中,当数组名作为参数传入函数后,在函数内修改数组元素会直接修改原数组数据。这是因为C语言中数组名作为函数参数传递时,实际上传递的是数组首元素的地址(指针),而不是数组的副本。这种机制的本质是指针传递,具体如下:

1. 数组名的本质是指针

  • 数组名在大多数情况下会退化为指向数组首元素的指针。例如:
int arr[5] = {1, 2, 3, 4, 5};

此时 arr 等价于 &arr[0](即首元素 1 的地址)。

  • 当数组名作为参数传入函数时,函数接收的是该地址值(数组名也表示数组的首地址),而不是整个数组的拷贝
void modify(int arr[], int size) {
    arr[0] = 100; // 修改首元素
}

此处 arr 实际是 int* 类型(指针),而非整个数组。

2. 函数内通过指针直接操作原始内存

函数内部通过接收到的指针(即数组首地址)访问数组元素时,实际是在直接读写原始数组的内存。例如:

void modify(int *ptr, int size) {
    for (int i = 0; i < size; i++) {
        *(ptr + i) *= 2; // 通过指针算术运算修改元素
    }
}

此操作直接修改了原数组的内容,而非操作副本。

3. 与普通变量的值传递对比

  • 普通变量(如 int:传递的是值的副本,函数内修改不影响原始变量:
void change(int x) { x = 10; } // 不影响外部变量
  • 数组:传递的是地址,函数内通过地址修改的是同一块内存:
void changeArray(int arr[]) { arr[0] = 10; } // 直接影响原数组

这种差异源于 C 语言的设计选择:为避免复制大型数组的开销,采用指针传递。

4. 多维数组的传递机制

  • 二维数组作为参数时,同样传递首地址:
void modifyMatrix(int matrix[][4], int rows) {
    matrix[0][0] = 100; // 直接修改原始数据
}

需指定除第一维外的其他维度大小(如 [][4]),以便编译器计算地址偏移

5,核心原因

函数通过接收到的指针直接读写原始数组的内存地址,而非操作副本。这种“按地址传递”(Pass by Address)机制是 C 语言高效处理数组的核心设计,但也要求开发者谨慎管理内存与边界。

#include <stdio.h>

void modify(int arr[])
{
    arr[0] = 100; // 直接修改原数组的首元素
}

void modify_array(int * ptr, int size)
{
    for (int i = 0; i < size; i++)
    {
        *(ptr + i) *= 2;
    }
}

void print_array(int *ptr, int size)
{
    for (int i = 0; i < size; i++)
    {
        printf("%d -> %d\n", i, *(ptr + i));
    }
}

int main()
{
    int a[3] = {1, 2, 3};
    modify(a);
    printf("%d\n", a[0]); // 输出 100(而非 1)

    modify_array(a, 3);
    print_array(a, 3);
    return 0;
}
100
0 -> 200
1 -> 4
2 -> 6
在C语言中,创建一个函数来拷贝整个指针数组通常涉及到深拷贝或浅拷贝的行为,取决于你是想复制指针本身还是指向的内容。下面是一个简单的示例,用于复制指针数组及其指向的元素(浅拷贝),假设所有的元素都是同类型的: ```c #include <stdio.h> #include <stdlib.h> // 为了使用malloc() // 定义一个结构体(如果有复杂的对象) typedef struct { int value; } MyStruct; // 深拷贝指针函数,这里的浅拷贝是因为只复制地址 void copy_ptr_array(MyStruct** src, MyStruct** dest, int size) { // 首先检查是否有足够的内存分配新指针 if (!dest || !size) { printf("Invalid input.\n"); return; } *dest = malloc(size * sizeof(MyStruct*)); // 分配新的数组 // 拷贝源数组中的每个指针 for (int i = 0; i < size; i++) { if (*src[i]) { // 如果指针有效 (*dest)[i] = *src[i]; // 复制指针 } else { (*dest)[i] = NULL; // 或者设置为NULL,如果你不想复制无效指针 } } } int main() { MyStruct my_structs[] = { {1}, {2}, {3} }; MyStruct* copied_structs; int array_size = sizeof(my_structs) / sizeof(my_structs[0]); // 调用拷贝函数 copy_ptr_array(my_structs, &copied_structs, array_size); // 现在你可以遍历并打印复制后的数组 for (int i = 0; i < array_size; i++) { printf("copied_structs[%d].value = %d\n", i, copied_structs[i]->value); } // 清理内存 free(copied_structs); // 如果不需要保留始指针,记得释放分配的内存 return 0; }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值