C语言中,函数的数组参数在传递时会退化为指针,导致它们的大小与直接在 main 函数或其他地方声明的数组大小不同。也就是说,当一个数组作为参数传递给函数时,编译器会将数组退化为指针类型,因此在函数内部计算该参数的大小会得到指针的大小,而不是数组的实际大小。

1、数组参数会退化为指针的原因

C语言中,数组作为参数传递给函数时实际上传递的是指向数组首元素的指针,而不是整个数组。这样设计的原因是效率:传递指针比传递整个数组要高效得多。

因此,当你在函数中定义一个数组参数时,比如 int arr[] int arr[10],编译器将其视为 int* arr,即一个指向 int 的指针,而不是实际的数组。由于 arr 退化为指针,调用 sizeof(arr) 会返回指针的大小,而不是数组的大小。

#include <stdio.h>

void printArraySize(int arr[]) {
    printf("Size of array parameter in function: %zu bytes\n", sizeof(arr));
}

int main() {
    int arr[10];  // 定义一个大小为10的数组
    printf("Size of array in main: %zu bytes\n", sizeof(arr));

    printArraySize(arr);  // 传递数组到函数

    return 0;
}

2、函数中获取数组的实际大小的方法

由于数组在传递给函数时会退化为指针,如果我们需要在函数中知道数组的实际大小,可以通过传递数组的长度信息。

#include <stdio.h>

void printArray(int arr[], size_t size) {
    printf("Array size in function: %zu\n", size);
    for (size_t i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() {
    int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    size_t size = sizeof(arr) / sizeof(arr[0]);  // 计算数组元素个数

    printf("Array size in main: %zu\n", size);
    printArray(arr, size);  // 将数组和大小传递给函数

    return 0;
}

3、函数中使用指针加长度的方式

使用指针加长度的方式传递数组时,我们将数组的首地址和数组的长度一同传递给函数。这样,函数可以使用指针来操作数组,并根据传入的长度来遍历数组。

#include <stdio.h>

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

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int length = sizeof(arr) / sizeof(arr[0]); // 计算数组长度

    printArray(arr, length); // 传递数组指针和长度
    return 0;
}

4、数组首地址和指针区别

数组首地址,在 sizeof(arr) 中,arr 是整个数组,sizeof(arr) 返回整个数组的大小。指针,在 sizeof(ptr)中,ptr 是一个指针变量,sizeof(ptr) 返回的是指针的大小(通常在 32 位系统上是 4 字节,在 64 位系统上是 8 字节),与数组大小无关。

当数组作为参数传递给函数时,数组会退化为指针,传递的实际上是数组首地址,而不是整个数组。即使在函数定义中使用数组的形式(如 int arr[]),本质上它等同于指针 int *arr。指针作为参数传递时,本质上就是传递指针的值(地址),并且在函数内部可以改变指针指向的内容。

#include <stdio.h>

void foo(int arr[]) {
    // 在函数中,数组名退化为指针
    printf("Inside foo, sizeof(arr): %zu (array as parameter, treated as pointer)\n", sizeof(arr));
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5}; // 定义一个数组
    int *ptr = arr;               // 指针指向数组首地址

    // sizeof 运算符的不同
    printf("Size of array (sizeof(arr)): %zu (total array size)\n", sizeof(arr));
    printf("Size of pointer (sizeof(ptr)): %zu (pointer size)\n", sizeof(ptr));

    // 修改指针的指向
    printf("Pointer before incrementing: %p\n", (void *)ptr);
    ptr++; // 合法,指针可以移动到下一个元素
    printf("Pointer after incrementing: %p\n", (void *)ptr);

    // 尝试直接修改数组名(会报错,注释掉以防止编译错误)
    // arr = ptr; // 错误:数组名是常量,不能赋值

    // 调用函数,观察数组在函数中的行为
    foo(arr);

    return 0;
}

推荐文档

相关文档

大家感兴趣的内容

随机列表