C语言 数组的地址和数组的首元素指针

C语言中,数组的地址和数组的首元素指针表现得非常相似,因此在许多表达式中,它们可以互换使用。这种行为源于C语言的数组和指针的关系。具体来说,在绝大多数情况下,数组的名称会退化为指向其首元素的指针。因此,数组的地址和其首元素的地址是相同的。

1、数组名作为指针

在表达式中使用数组名时,数组名会自动退化为指向首元素的指针。

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    // 打印数组的地址
    printf("arr: %p\n", (void*)arr);
    printf("&arr[0]: %p\n", (void*)&arr[0]);

    // 比较数组名和首元素指针
    if (arr == &arr[0]) {
        printf("arr == &arr[0] 为真\n");
    } else {
        printf("arr != &arr[0] 为假\n");
    }

    return 0;
}

在大多数情况下,arr 会退化为 &arr[0],即指向数组首元素的指针。arr&arr[0] 都指向数组的第一个元素的地址, 也就是arr == &arr[0]

2、&arr 和 arr 的区别

尽管 arr &arr 在地址上是相同的,但它们的类型不同,因此在使用时需要注意。arr 退化为 int* 类型,指向数组的首元素。&arr 的类型是 int(*)[5],表示一个指向包含5个 int 的数组的指针。

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    printf("arr       = %p\n", (void*)arr);        // 打印数组首元素的地址
    printf("&arr      = %p\n", (void*)&arr);       // 打印数组的地址(与arr相同)
    printf("&arr[0]   = %p\n", (void*)&arr[0]);    // 打印首元素的地址(与arr相同)
    
    printf("sizeof(arr) = %zu\n", sizeof(arr));    // 输出数组的总大小(20字节)
    printf("sizeof(&arr) = %zu\n", sizeof(&arr));  // 输出指针的大小(取决于系统,通常为8字节)
    
    return 0;
}

arr&arr&arr[0] 的值(地址)相同,因为它们都指向数组的第一个元素。sizeof(arr) 是整个数组的大小(20字节),而 sizeof(&arr) 是一个指针的大小(通常是8字节)。arr int* 类型的指针,而 &arr int(*)[5] 类型的指针,它们的类型不同。

3、不发生退化的情况

数组名不会总是退化为指针,如下面几种情况,

1)使用 sizeof 运算符

使用sizeof 运算符时,sizeof(arr) 会返回数组的总大小,而不是指针的大小。

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    printf("Size of arr: %lu\n", sizeof(arr));         // 输出数组的总大小
    printf("Size of arr[0]: %lu\n", sizeof(arr[0]));   // 输出数组中每个元素的大小
    printf("Number of elements in arr: %lu\n", sizeof(arr) / sizeof(arr[0])); // 计算数组元素数量
    return 0;
}

2) 使用 & 运算符

使用& 运算符时,&arr 返回整个数组的地址,类型为 int(*)[5]

#include <stdio.h>

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int *ptr = arr;           // ptr 是指向数组第一个元素的指针,类型为 int*
    int (*arr_ptr)[5] = &arr; // arr_ptr 是指向整个数组的指针,类型为 int (*)[5]

    printf("Address of arr (using &arr): %p\n", (void*)&arr);
    printf("Address of arr (using arr): %p\n", (void*)arr);
    return 0;
}

3) 字符串字面量初始化

在字符串字面量初始化时,例如 char arr[] = "hello"; 会将整个字符串字面量复制到 arr 中。

#include <stdio.h>

int main() {
    char arr[] = "hello";    // 字符串字面量 "hello" 被复制到 arr 中
    printf("Array content: %s\n", arr); // 输出整个字符串
    printf("Size of arr: %lu\n", sizeof(arr)); // 包含了空字符 '\0'
    return 0;
}

推荐阅读
cjavapy编程之路首页