【C语言初阶】:数组在面试中的陷阱

★数组

数组:是一组相同类型的集合,有一维数组,二维数组(矩阵),三维数组和字符数组。

●一维数组


一维数组的创建:直接上例子(int  arr1[10])。注:数组在创建的时候,[ ]中要给常量猜可以,不能使用变量。
◆陷阱:const关键字修饰的变量在C语言中是具有常属性的变量,依然是一个变量,不可以放在数组的[ ]中;但是在C++中const修饰的变量是一个常量,可以放在数组的[ ]中。

一维数组的初始化:在创建数组的同时给数组的内容一些合理初始值。(下面是例子:)
int arr1[10]={1,2,3}
//数组的初始值为1,2,3,0,0,0,0,0,0,0
int arr2[]={1,2,3,4}
//数组的初始值为1,2,3,4
int arr3[5]={1,2,3,4,5}
char arr4[]={'a','b','c'}
char arr5[]="abcdef"

陷阱:

char  arr1[]="abc"//可以以%s形式打印,用sizeof计算值为4,因为还有'\0'字符结束标志
char  arr2[3]={'a','b','c'};//不能以%s形式打印,因为没有'\0'字符结束标志,打印出来的结果为随机值
char *p="abcdef"//p为一个指针变量,它存的是首元素a的地址

一维数组的使用:

1.数组的使用是通过下标来访问的,下标是从0开始的。
2.数组的大小可以通过sizeof(arr)/sizeof(arr[0])求得。

一维数组在内存中的存储:数组在内存中是连续存放的(请看下面例子的输出结果是什么?)
#include<stdio.h>

int main()
{
	int arr[5] = { 0 };
	int  i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]);i++)\
	{
		printf("&arr[%d]=%p\n", i, &arr[i]);
	}
	system("pause");
	return 0;
}
输出结果:
一维数组的指针访问:请看下面的例子
#include<stdio.h>
#include<windows.h>

int main()
{
	int arr[10] = { 0 };
	int i = 0;
	int *p = arr;//将数组的首元素赋给指针变量p
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		*(p + i) = i;//(p+i)是第i个元素的地址
	}
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d\n", *(p + i));
	}
	system("pause");
	return 0;
}

◆一维数组的数组名其实就是数组首元素的地址,通过对数组名+整数的运算,可以获得到数组每个元素的地址。
陷阱:
printf("%p\n",arr);输出的是数组首元素的地址
printf("%p\n",&arr[0]);输出的是数组首元素的地址
printf("%p\n",&arr);输出的是数组的地址对它进行加1操作跳过整个数组

●二维数组

二维数组的创建:(直接上例子)
int arr[3][4];
char  arr[3][5];
double arr[2][4];

二维数组的初始化:(直接上例子)
int arr[3][4]={1,2,3,4};
int arr[3][4]={{1,2},{4,3}};
int arr[][4]={{2,3},{4,5}};

陷阱:在二维数组初始化的时候,因为它在内存中也是连续存储的,所以可以看成是一行,可以根据列确定数组中的元素。因此初始化的时候行可以省略,但是列一定不能省略。


二维数组的使用:
#include<stdio.h>
#include<windows.h>

int main()
{
	int arr[3][4] = { 0 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			arr[i][j] = i * 4 + j + 1;//给二维数组赋值1-12
		}
	}
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
	system("pause");
	return 0;
}

二维数组的使用也是根据下标的方式使用的。

二维数组在内存中的存储:在内存中连续存储(大概是下面这幅图的样子!)

一维数组的指针访问:请看下面的例子
#include<stdio.h>

int main()
{
	int arr[3][4] = { 0 };
	int *p = &arr[0][0];//数组首元素的地址
	int i = 0;
	for (i = 0; i < 12; i++)
	{
		*(p + i) = i;//(p+i)是数组i个元素的地址,然后在解引用,给数组每个元素赋值
	}
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 4; j++)
		{
			printf("%d ", arr[i][j]);
		}
	}
	return 0;
}
陷阱:数组名代表整个数组只有两种情况:

①sizeof(数组名),用来求数组的大小。
②&数组名,取出来的是整个数组的地址

前方高能!!!接下来的文章是关于数组的运算,非常重要哦。

▲有关数组的运算
一维数组:
#include<stdio.h>

int main()
{
	int a[] = { 1, 2, 3, 4 };
	printf("%d\n", sizeof(a));// 16  这里的a代表的是整个数组
	printf("%d\n", sizeof(a+0));//4  首元素的地址
	printf("%d\n", sizeof(*a));//4  a[0]类型所占大小
	printf("%d\n", sizeof(a+1));//4   第二个元素的地址
	printf("%d\n", sizeof(a[1]));//4 a[1]类型所占大小
	printf("%d\n", sizeof(&a));//4  整个数组的地址,这里和首元素的地址相同,但进行加1操作就不一样了
	printf("%d\n", sizeof(*&a));//16  对数组的地址进行解引用
	printf("%d\n", sizeof(&a+1));//4  指向4后边的指针(地址)
	printf("%d\n", sizeof(&a[0]));//4  a[0]的地址
	printf("%d\n", sizeof(&a[0]+1));//4 a[1]的地址

	return 0;
}

字符数组:
#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
	//sizeof
	printf("%d\n", sizeof(arr));//6  数组有6个字符,没有'/0',都是字符类型
	printf("%d\n", sizeof(arr+0));//4  数组首元素的地址
	printf("%d\n", sizeof(*arr));//1  a的类型所占空间
	printf("%d\n", sizeof(arr[1]));//1  b的类型所占空间
	printf("%d\n", sizeof(&arr));//4   整个数组的地址
	printf("%d\n", sizeof(&arr+1));//4  指向f后边的指针
	printf("%d\n", sizeof(&arr[0]+1));//4  第二个元素的地址
	//strlen
	printf("%d\n", strlen(arr));//随机值  数组没有'\0'结束标志,停不下来
	printf("%d\n", strlen(arr+0));//随机值  数组首元素的地址,没有'\0'
	printf("%d\n", strlen(*arr));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(arr[1]));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(&arr));//随机值  数组的地址,没有'\0'
	printf("%d\n", strlen(&arr+1));//随机值 指向f后边的指针
	printf("%d\n", strlen(&arr[0]+1));//随机值 第二个元素的地址
	return 0;
}
#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = "abcdef";
	//sizeof
	printf("%d\n", sizeof(arr));//7  //数组一共有7个字符,包括'/0',他们的类型都是字符
	printf("%d\n", sizeof(arr+0));//4 首元素的地址,指针变量为4个字节
	printf("%d\n", sizeof(*arr));//1  arr[0],a的类型为字符
	printf("%d\n", sizeof(arr[1]));//1  b的类型为字符
	printf("%d\n", sizeof(&arr));//4  整个数组的地址
	printf("%d\n", sizeof(&arr+1));//4 指向arr数组后的指针
	printf("%d\n", sizeof(&arr[0]+1));//4 第二个元素的地址
	//strlen
	printf("%d\n", strlen(arr));//6  不算'\0',有6个字符
	printf("%d\n", strlen(arr+0));//6  数组首元素的地址
	printf("%d\n", strlen(*arr));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(arr[1]));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(&arr));//6  数组的地址,这里和首元素地址相同但意义不同
	printf("%d\n", strlen(&arr+1));//随机值 指向f后边的指针
	printf("%d\n", strlen(&arr[0]+1));//5 第二个元素的地址
	
}
#include<stdio.h>
#include<string.h>

int main()
{
	char *p = "abcdef";
	//sizeof
	printf("%d\n", sizeof(p));//4 p是一个指针变量,为a的地址
	printf("%d\n", sizeof(p+1));//4  第二个元素的地址
	printf("%d\n", sizeof(*p));//1  *p=a,a的类型为char
	printf("%d\n", sizeof(p[0]));//1 相当于对p进行解引用操作
	printf("%d\n", sizeof(&p));//4  指针变量p的地址,为二级指针
	printf("%d\n", sizeof(&p+1));//4 还是地址
	printf("%d\n", sizeof(&p[0]+1));//第二个元素的地址
	//strlen
	printf("%d\n", strlen(p));//6 从首元素开始数到'\0'结束
	printf("%d\n", strlen(p + 1));//5 第二个元素的地址,从第二个开始数
	printf("%d\n", strlen(*p));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(p[0]));//错误的表达式  strlen函数接受的是一个指针,而不是值
	printf("%d\n", strlen(&p));//随机值,二级指针不能确定
	printf("%d\n", strlen(&p + 1));//随机值
	printf("%d\n", strlen(&p[0] + 1));//5  第二个元素的地址
}

陷阱:对与以上三个关于字符数组的运算,一定要掌握sizeof运算符和strlen函数的区别,不知道的朋友请戳——> 区别
二维数组
#include<stdio.h>
#include<string.h>

int main()
{
	int a[3][4] = { 0 };
	printf("%d\n", sizeof(a));//48 这里的数组名表示整个数组
	printf("%d\n", sizeof(a[0][0]));//4 首元素的类型为int
	printf("%d\n", sizeof(a[0]));//16 可以把a[0]当做第一行数组的数组名
	printf("%d\n", sizeof(a[0]+1));//4  a[0]降级成a[0][0]的地址,加1变成a[0][1]的地址
	printf("%d\n", sizeof(a+1));//4  a降级成数组第一行的地址,在加1成第二行的地址
	printf("%d\n", sizeof(&a[0]+1));//4  第二行的地址
	printf("%d\n", sizeof(*a));//16   a降级成数组第一行的地址,在进行解引用操作,和sizeof(a[0])等价
	printf("%d\n", sizeof(a[3]));//16  sizeof内部的表达式不运算,由a[0]推出a[3]的类型,和a[0]是等价的
	return 0;
}

数组作为函数参数:(请看下边的例子,这样可以吗?)
void binary_search(int arr[]);
{  
       int sz=sizeof(arr)/sizeof(arr[0]);
        ....
        ....
}
陷阱:数组作为函数参数的时候,不会把整个数组传递过去,而是把数组首元素的地址传递过去了,所以sizeof(arr)/sizeof(arr[0])这个计算值是1。如果要用到数组的长度,应该当做参数直接传给地址。这里的int arr[ ]表示的是指针,和int *arr等价。

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/79916875