C语言 - 数组

数组是一组相同类型元素的集合,男同女同狂喜!(不是


前言

本篇笔记重点描述C语言中一维数组和二维数组的具体使用。


一、C语言中一维数组的创建和初始化

1.一维数组的创建

注:数组创建,在C99标准之前, [ ] 中要给一个常量才可以,不能使用变量。在C99标准支持了变长数 组的概念,数组的大小可以使用变量指定,但是数组不能初始化

type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小
//代码1
int arr1[10];
//即int为数组类型,数组里面的变量类型为int,arr1为数组名

//代码2
int count = 10;
int arr2[count];//数组时候可以正常创建?

//代码3
char arr3[10]; float arr4[1]; double arr5[20];

2.一维数组的初始化

数组的初始化和变量的初始化有细微的区别。
数组的初始化有两种:

1、普通初始化,如果想给数组初始化应该给一个{ }
2、完全初始化,如果[10]后面的{ }没给满10个数,那就是不完全初始化,后面会默认补\0

举个例子:

数组的普通初始化和完全初始化
int a = 10; //变量初始化
int arr[10] = {1,2,3,4,5,6,7,8,9,10}; //完全初始化
int arr[10] = {1,2,3,4}; //不完全初始化
//--------
int arr[5] = {1,2,3,4,5};
int arr2[ ] = {1,2,3,4,5};
//上面两串代码是完全等价的

注:如果[ ]没有指定大小的话,它会根据后面{ }内容来确定我们的数组初始化几个元素

3.一维数组的使用

[ ]是下标引用操作符。

数组的使用方式
#include <stdio.h>
int main(){
int arr[10] = { 0 };

arr [4] = 5;//[] - 下标引用符
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
//sizeof(arr)算的是整个数组的大小,算的是字节
//sizeof(arr[0])算的是第一个元素的大小。
//总大小除以第一个元素的大小就是元素的个数

for(i = 0; i < sz; i++){
 printf(" %d " , arr[i]);
}
return 0; 
}

4.一维数组在内存中的存储

数组在int类型中,每个元素都差4个字节,也就是说4个字节为一个元素。

1、一维数组在内存中是连续存放的!
2、随着数组下标的增长,地址是由低到高变化的!
3、数组名是数组首元素的地址!
4、整型数组是没有\0的,只有字符数组里面才有!

#include <stdio.h>
int main() {
    int arr[10] = {0};
    int i = 0;
    int sz = sizeof(arr)/sizeof(arr[0]);
    for(i=0; i<sz; ++i)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }
//输出结果为电脑内存的地址,而且每个都相隔4个字节
return 0; 
}

二、C语言中二维数组的创建和初始化

1.二维数组的创建

二维数组和一维数组的创建只是形式上的不同而已。

//数组创建
int arr[3][4]; char arr[3][5]; double arr[2][4];

2.二维数组的初始化

二维数组的初始化,行可以省略,列不能省略。

//数组初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{4,5}};
int arr[][4] = {{2,3},{4,5}};
//二维数组如果有初始化,行可以省略,列不能省略

3.二维数组的使用

二维数组的使用也是和一维数组一样使用下标来使用。
另外需要注意的是,二维数组中第一行的行号是0,第一列列号是0。

#include <stdio.h>
int main() {
    int arr[3][4];
    int i = 0;
    for(i=0; i<3; i++)
    {
        int j = 0;
        for(j=0; j<4; j++)
        {
       printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
       //%p - 是按地址的格式打印 - 十六进制的打印
        }
}
return 0; }
} }
for(i=0; i<3; i++)
{
    int j = 0;
    for(j=0; j<4; j++)
    {
            printf("%d ", arr[i][j]);
        }
}
return 0; }

%p - 是按地址的格式打印 - 十六进制的打印

4.二维数组在内存中的储存

二维数组在内存中的储存和一维数组一样,这里我们尝试打印二维数组的每个元素。

#include <stdio.h>
int main() {
    int arr[3][4];
    int i = 0;
    for(i=0; i<3; i++){
      int j = 0;
      for(j=0; j<4; j++){
      printf("&arr[%d][%d] = %p\n", i, j,&arr[i][j]);
}
}
return 0; 
}

注:二维数组在内存中也是连续存放的!
一行内部连续,跨行也是连续的!

由此我们可知为什么行可以省略,列不能省略。因为计算机存储形式决定了,列起到划分区域的作用。

三、C语言中数组作为函数参数

某些场景,我们可能需要使用数组来作为参数传个函数,比如我们想实现一个冒泡排序函数(这里涉及了一些算法思想)

冒泡排序的思想:两两相邻的元素进行比较,并且可能的话需要交换。

1.冒泡排序函数的设计

#include <stdio.h>
void bubble_sort(int arr[])
{
  //计算数组元素个数
  int sz = sizeof(arr) / sizeof(arr[0]);//err
  //确认躺数
  int i = 0;
  for(i = 0; i < sz-1; i++){
  	//一趟冒泡排序的过程
  int j = 0;
  	for(j = 0; j < sz-1-i; j++){
  	if(arr[j] > arr[j + 1]){
  		//交换
  		int tmp = arr[j];
  		arr[j] = arr[j + 1];
  		arr[j + 1] = tmp;
  }
}
}
}
int main(){
	int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
	//排序为升序 - 冒泡排序
	bubble_sort(arr);
	return 0;
}

以上代码其实是错误示范。

数组在传参的时候,传过去的其实是数组首元素的地址。
这里的形参arr本质是指针。(不能这样写)

正确代码应该在传参外面先计算好个数,再进行传参

#include <stdio.h>
void bubble_sort(int arr[], int sz)
{
  //确认躺数
  int i = 0;
  for(i = 0; i < sz-1; i++){
  	//一趟冒泡排序的过程
  int j = 0;
  	for(j = 0; j < sz-1-i; j++){
  	if(arr[j] > arr[j + 1]){
  		//交换
  		int tmp = arr[j];
  		arr[j] = arr[j + 1];
  		arr[j + 1] = tmp;
  }
}
}
}
int main(){
	int arr[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
	//排序为升序 - 冒泡排序
	//计算数组元素个数
  	int sz = sizeof(arr) / sizeof(arr[0]);//err
	bubble_sort(arr, sz);
	return 0;
}

2.数组名是什么?

注:数组名就是首元素的地址!!!

#include <stdio.h>
int main() {
	int arr[10] = {1,23,4,5}; 
	printf("%p\n", arr); //数组名是首元素地址
	printf("%p\n", &arr[0]); 
	printf("%d\n", *arr); 
	//输出结果
	return 0; }

但是有两个例外!!!

1、sizeof(数组名) —数组名表示整个数组,计算的是整个数组的大小单位是字节。
2、&数组名 —数组名表示整个数组,取出的是整个数组的地址。

#include <stdio.h>
int main() {
	int arr[ 10 ] = { 0 };
	int sz = sizeof(arr); //数组名表示整个数组
	printf("%d\n, sz");
	//输出结果
	return 0; }

同时,数组的地址+1和数组首元素地址+1有着本质的不同。
这里可以自己去尝试一下以下的代码

#include <stdio.h>
int main() {
	int arr[ 10 ] = { 0 };
	printf("%p\n, &arr");//输出数组的地址
	printf("%p\n, &arr+1");//输出数组的地址+1

	printf("%p\n, arr");//输出数组首元素地址
	printf("%p\n, arr+1");//输出数组首元素地址+1
//+1前的输出结果是一样的,但是+1后的输出结果会完全不一样
	return 0; }

总结

1、数组是一堆相同类型的元素的集合。
2、在数组初始化的时候如果在[ ]内没有指定大小,则会根据{ }的内容来确定数组初始化有几个元素。
3、数组在内存中是连续存放的,无论是一维数组还是二维数组
4、数组最重要的一个点,数组名就是首元素的地址!!!(这个很重要)
5、数组地址+1和数组首元素地址+1有着本质的不同,但一个同样的数组地址和数组首元素地址是相同的。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值