数组-C语言

目录

1.一维数组

1.1 数组的创建

1.2 数组的初始化

1.3 一维数组的使用

1.4 一维数组在内存中的存储

2.二维数组

2.1 二维数组的创建

2.2 二维数组的初始化

2.3 二维数组的使用

2.4 二维数组在内存中的存储

3.数组越界

4.数组作为函数参数

4.1 冒泡排序函数的错误设计

4.2 数组名是什么

4.3 冒泡排序函数的正确设计


1.一维数组

1.1 数组的创建

①数组:一组相同类型元素的集合

②数组的创建方式:

1)type_t arr_name [const_n];

其中type_t 是指数组的元素类型,const_n 是一个常量表达式,用来指定数组的大小

2)创建一维动态数组

int main()
{   
    int n;
	int* a;
	scanf_s("%d", &n);
	a = (int*)malloc(sizeof(int));
	for (int i = 0; i < n; i++)
	{
		scanf_s("%d", &a[i]);
	}
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
    return 0;
}

③实例

int arr1[8];
char arr2[5];
float arr3[1];
double arr4[20];

在C99标准之前, [] 中要给一个常量才可以,不能使用变量,C99标准支持变长数
组的概念,数组的大小可以是变量(VS2019不支持C99)

int n = 8;
int arr[n];

1.2 数组的初始化

①完全初始化

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

②不完全初始化

int arr[10] = { 1,2,3,4,5 };

🐖:数组在创建的时候如果想不指定数组的确定的大小就得初始化,数组的元素个数根据初始化的内容来确定

int arr2[] = { 1,2,3,4,5 };

相当于

int arr2[5] = { 1,2,3,4,5 };

③字符数的初始化

char ch1[5] = { 'b','i','t' };
char ch2[] = { 'b','i','t' };

ch1初始化为:b i t \0 \0

ch2初始化为:b i t初始化为:b i t

char ch1[5] = "bit";
char ch2[] = "bit";

ch1初始化为:b  i  t  \0  \0

ch2初始化为:b  i  t  \0  

char arr1[] = "abc";
char arr2[3] = { 'a','b','c' };

arr1初始化为:a b c \0

arr2初始化为:a b c 

char ch1[] = "bit";
char ch2[] = { 'b','i','t' };
printf("%s\n", ch1);
printf("%s", ch2);

输出:

bit
bit烫烫烫烫蘠it

这是因为在遇到 \0 时才会停止打印,ch1初始化时末尾已有 \0 ,而ch2没有,因此在打印ch2时会一直向后打印,直到遇到 \0 才会停止打印

同理,ch2的长度为随机值

char ch1[] = "bit";
char ch2[] = { 'b','i','t' };
printf("%d ", strlen(ch1));
printf("%d", strlen(ch2));

输出:3 15

1.3 一维数组的使用

①数组下标从0开始

 [ ]:下标引用操作符

arr[4]:arr数组中的第五个元素

②计算数组的元素个数

 int sz = sizeof(arr)/sizeof(arr[0]);

③对数组内容赋值,数组是使用下标来访问的,下标从0开始

int i = 0;//下标
for(i=0; i<10; i++)
{
    arr[i] = i;
}

④输出数组的内容

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

1.4 一维数组在内存中的存储

int main()
{
	int arr[10] = { 0 };
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("&arr[%d]=%p\n", i, &arr[i]);//以16进制输出地址
	}
	return 0;
}

输出:

&arr[0]=0093FDFC
&arr[1]=0093FE00
&arr[2]=0093FE04
&arr[3]=0093FE08
&arr[4]=0093FE0C
&arr[5]=0093FE10
&arr[6]=0093FE14
&arr[7]=0093FE18
&arr[8]=0093FE1C
&arr[9]=0093FE20

①一维数组在内存中是连续存放的

②随着数组下标的增长,地址是由低到高变化的

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;//数组名是数组首元素的地址
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

输出:1 2 3 4 5 6 7 8 9 10

2.二维数组

2.1 二维数组的创建

int arr[3][4];
char arr[3][5];
double arr[2][4];

②二维动态数组的创建

int** a;
int n;
scanf_s("%d", &n);
a = (int**)calloc(sizeof(int*), n);
for (int i = 0; i < n; i++)
{
	*(a + i) = (int*)calloc(sizeof(int), n);
}

2.2 二维数组的初始化

①完全初始化

int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };

②不完全初始化(后面补0)

int arr[3][4] = { 1,2,3,4,5,6,7,8 };
int arr1[3][4] = { {1,2},{4,5} };

🐖:二维数组如果有初始化,行可以省略,列不能省略    

int arr[][4] = { {2,3},{4,5} };

2.3 二维数组的使用

二维数组的使用也是通过下标的方式,行、列下标都是从0开始

 arr[1][2]表示第2行第3列的数字

int main()
{
	int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int i = 0, j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

2.4 二维数组在内存中的存储

int main()
{
	int a[][4] = { {1,2} ,{3,4},{5,6} };
	int i = 0, j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("&a[%d][%d]=%p\n", i, j, &a[i][j]);
		}
	}
	return 0;
}

输出:

&a[0][0]=00C3F8D8
&a[0][1]=00C3F8DC
&a[0][2]=00C3F8E0
&a[1][0]=00C3F8E4
&a[1][1]=00C3F8E8
&a[1][2]=00C3F8EC
&a[2][0]=00C3F8F0
&a[2][1]=00C3F8F4
&a[2][2]=00C3F8F8

二维数组在内存中也是连续存储的

int main()
{
	int a[][4] = { {1,2} ,{3,4},{5,6} };
	int i = 0, j = 0;
	int* p = &a[0][0];
	for (i = 0; i < 9; i++)
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

 输出:1 2 0 3 4 0 5 6 0

3.数组越界

数组的下标是有范围限制的。数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1,所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问

C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的

4.数组作为函数参数

4.1 冒泡排序函数的错误设计

错误示例:

void bubble_sort(int arr[])
{
  int sz = sizeof(arr)/sizeof(arr[0]);//这样对吗?
  int i = 0;
  for(i=0; i<sz-1; i++)
  {
    int j = 0;
    for(j=0; j<sz-i-1; j++)
    {
      if(arr[j] > arr[j+1])
      {
        int tmp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = tmp;
      }
    }
  }
}
int main()
{
  int arr[] = {3,1,7,5,8,9,0,2,4,6};
  bubble_sort(arr);//是否可以正常排序?
  for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
 {
    printf("%d ", arr[i]);
 }
  return 0;
}

这是因为形参arr本身是指针,数组传参的时候,实际上传递的是数组首元素的地址

4.2 数组名是什么

数组名是数组首元素的地址

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr[0]);
	return 0;
}

输出:

001FFE90
001FFE90

特列1:sizeof(数组名)--数组名表示的是整个数组,计算的是整个数组的大小,单位是字节

int main()
{
	int arr[10] = { 0 };
	printf("%d\n", sizeof(arr));
	return 0;
}

输出:40

特列2:&数组名--数组名表示的是整个数组,取出的是整个数组的地址

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", arr);
	printf("%p\n", &arr);
	printf("%p\n", &arr[0]);
	return 0;
}

输出:

00F8FAF8
00F8FAF8
00F8FAF8

int main()
{
	int arr[10] = { 0 };
	printf("%p\n", &arr);
	printf("%p\n", &arr+1);

	printf("%p\n", arr);
	printf("%p\n", arr+1);
	return 0;
}

输出:

005FFCAC
005FFCD4
005FFCAC
005FFCB0

4.3 冒泡排序函数的正确设计

void sort(int arr[],int sz)
{
	
	int i = 0, j = 0;
	for (i = 0; i < 10; i++)
	{
		for (j = 0; j <sz-1-i ; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int t = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = t;
			}
		}
	}
}
int main()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	sort(arr,sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

输出:0 1 2 3 4 5 6 7 8 9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值