【C语言】一维数组

声明语法格式

c 复制代码
// 1. 先声明数组长度,后赋值
int arr01[10];
// 此时,数组元素的值为随机的垃圾值
printf("%d\n", arr01[0]);

// 2. 声明的时候同时初始化
int arr02[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
printf("%d\n", arr02[1]);   // 输出 2

// 3. 部分初始化,其他元素的值为默认值
int arr03[10] = {1, 2, 3};
printf("%d -- %d\n", arr03[0], arr03[9]);   // 输出 1 -- 0

// 4. 省略长度,编译器会自动计算数组长度
int arr04[] = {1, 2, 3, 4};
printf("arr04 size = %llu\n", sizeof(arr04) / sizeof(arr04[0]));    // 输出 arr04 size = 4

求数组长度

sizeof(arr): 整个数组占用的字节数

sizeof(arr[0]): 数组中单个元素占用的字节数

sizeof(arr) / sizeof(arr[0]): 计算出数组中元素的个数

数组作为函数的参数传递时,会退化为指针。在函数内不能使用sizeof(arr)计算数组占用的字节数

c 复制代码
int arr[] = {0, 1, 2, 3, 4, 5};
printf("数组占用的字节数: %llu\n", sizeof(arr));    // 输出数组占用的字节数 24
printf("数组单个元素占用的字节数: %llu\n", sizeof(arr[0])); // 输出数组单个元素占用的字节数 4
printf("数组元素个数:%llu\n", sizeof(arr) / sizeof(arr[0]));  // 输出数组元素个数 6

数组遍历

c 复制代码
int arr[] = {0, 1, 2, 3, 4, 5};
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    printf("%d\t", arr[i]);
}
printf("\n");

数组名

  • 数组名是指针常量(int * const arr),无法修改(指向的值是可以修改的)
c 复制代码
int arr[] = {0, 1, 2, 3, 4, 5};
// 数组名是一个常量指针,不能修改
// arr = NULL;

// 指向的值是可以修改的
printf("%d\n", *(arr+5));   // 5
*(arr+5) = 10;
printf("%d\n", *(arr+5));   // 10
  • 数组名的本质

    • 除了一下两种情况,一维数组的数组名是指向首个元素的指针:

      • sizeof计算数组占用的字节数
      • 对数组名进行取地址操作,取得是整个数组的首地址(对数组指针+1会跳过整个数组)
  • 数组下标访问可以是负数,但是需要注意越界问题;

数组传参

!WARNING

数组名在传参时会退化为指向首元素的指针,因此数组传参时需要传递数组的长度(数组元素个数)

第一种方式,int arr[] 方式,更直观

c 复制代码
int sum(int arr[], int length) {
	// 这里数组名退化为指向首元素的指针,输出结果为8(64位平台)
    printf("arr size = %llu \n", sizeof(arr));

    int count = 0;
    for (int i=0; i< length; i++) {
        count += arr[i];
    }
    return count;
}

int main() {
    int arr[] = {0, 1, 2, 3, 4};
    int count = sum(arr, 5);
    printf("count = %d\n", count);  // 输出 count = 10
}

在for循环内可以通过指针方式访问元素:

c 复制代码
// 指针方式方式元素
printf("%d\n", *(arr + i));
  • 第二种方式,int * p 指针妨害
c 复制代码
int sum(int *arr, int length) {

    // 这里数组名退化为指向首元素的指针,输出结果为8(64位平台)
    printf("arr size = %llu \n", sizeof(arr));

    int count = 0;
    for (int i=0; i< length; i++) {
        // 数组方式访问元素
        count += arr[i];
        // 指针方式方式元素
        printf("%d\n", *(arr + i));
    }
    return count;
}

int main() {
    int arr[] = {0, 1, 2, 3, 4};
    int count = sum(arr, 5);
    printf("count = %d\n", count);  // 输出 count = 10
}

一维数组指针定义

数组指针指向数组的指针,指针变量,存放整个数组的地址

语法:数据类型 (*p)[数组长度]

!TIP

指针数组存放指针的数组,数组,每个元素是指针

语法:数据类型 *p[]

  • (*p)[] 括号包住指针 → 数组指针(一个指针)
  • *p[] 星号和数组结合 → 指针数组(一堆指针)
c 复制代码
int main() {
    int arr[] = {0, 1, 2, 3, 4};

    // 第一种方式,直接定义
    int (*arr_p1)[5] = &arr;
    printf("%p\n", arr_p1);

    // 第二种方式,先定义数组的类型,然后根据数组类型定义数组指针
    typedef int (ARRAY_TYPE)[5];        // 这是一个包含了5个int类型元素的数组类型
    ARRAY_TYPE* arr_p2 = &arr;
    printf("%p\n", arr_p2);

    // 第三种类型,先定义数组指针类型,然后定义数组指针
    typedef int (*ARRAY_POINTER)[5];    // 这是一个包含了5个int类型元素的数组指针类型
    ARRAY_POINTER arr_p3 = &arr;
    printf("%p\n", arr_p3);
}

注意:

  • &arr是整个数组的地址,类型为int (*)[数组长度],只能赋值给同类型数组指针;
  • arr:首元素地址 int *,不能直接赋值给 int (*)[5],类型不匹配编译报错;
  • arr_p1存储的是整个数组的首地址,arr_p1 + 1会跳过整个数组,不是跳过一个元素;