数组、指针总结【面试题】
文章目录
- 0. 补充知识
- 数组笔试题
- 1. 一维数组
- 1.1 字符数组
- 1.1.1 sizeof
- 1.1.2 strlen
- 1.2 二维数组
- 2. 指针笔试题
0. 补充知识
在进入数组与指针的练习时,我们先来复习以下以下的知识点,这可以帮助我们更好的理解下面练习
- 数组是一组能存放相同类型的类型的元素,数组的大小取决于数组元素个数和元素类型
- 指针是地址,口头语的指针是指针变量,大小是4/8字节
- 数组是数组,指针是指针,两者不等价,只有在传参时数组会退化为指针
- 数组名是首元素的地址,这个地址可以存放在指针变量中,因此可以将数组和指针练习起来
- 二维数组
arr[m][n]
可以看成是一个有m个元素的一维数组,每个数组元素是一个有n个元素的一维数组,因此二维数组名是有n个元素的一维数组的地址,多维数组以此类推- 只有当数组名单独放在sizeof内部和&数组名时,数组名才代表整个数组,其余情况数组名代表首元素的地址
- sizeof是编译期间进行的操作符,它是根据表达式的
类型属性
来进行求值,因此不需要知道表达式的值属性
,也不会对表达式进行运算- strlen是函数,函数的型参是
const char*
,通常实参是char*
,可以将char*
传给更安全的const char*
,如果传的参数不是const char*
类型,则在函数体内部会自动转换成const char*
来处理- 访问为定义地址时,不是一定会报错,如果访问的地址没有被其他程序调用,则不会报错,如果该地址被其他程序调用,则会报错
- 指针类型决定了(1)指针加减整数跳过的空间有多大(2)解引用指针的权限有多大
- 数组的下标引用实际上是间接引用的伪装
- 数据的存储模式有
大端存储
、小端存储
- 二维数组名等价于数组指针名
数组笔试题
1. 一维数组
//一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));
1.1 字符数组
1.1.1 sizeof
1.1.2 strlen
注:在34行中访问了未定义的地址,当这个地址被其他程序调用时会出现程序崩溃,否则不会崩溃
可以看见,程序崩溃后不会整形崩溃语句的后面语句
1.2 二维数组
注:sizeof不会对表达式进行运算,因此没有访问a[3],没有越界访问
2. 指针笔试题
2.
- p是一个大小为20字节的结构体指针,
指针+整数
的意义是跳过多少个字节,因此p+0x1相当于跳过1个结构体大小20个字节,第一个答案就是00100014- 将p强转为
unsigned long
类型,为整形,整形+0x1就是数值上+1,因此答案是00100001- 将p强转为
unsigned int*
类型,为指针,+1表示跨过一个int型,因此答案是00100004
注:%p打印格式是8位16进制,高位不足补0
- ptr1指向a[3]后面的一个元素,ptr[-1]代表*(ptr1-1),表示访问ptr1前面4个字节的元素即arr[3]
- ptr2情况较复杂,我们画字节数据的存储图(字节内容以16进制表示)(以小端存储为例)
a原本是int*类型的数据值是01的,强转为int型在+1,最后ptr2指向该位置
在解引用访问从ptr2向后面的4个字节,因为是小端存储,所以解引用得到的值是0x02000000
注:%x是有多少位16进制就打印多少位16进制
逗号表达式的值是最后一个表达式的值,因此数组a只有前3个元素赋值了1,3,5
p=a[0],因此p[0]相当于a[0][0],答案为1
p是一个指向具有4个元素数组的指针,可以看作是列数为4的二维数组名
二维数组在内存中是连续存放
的,因此二维数组元素arr[i][j]
实际上是arr[0][0]
后面i*列数+j
个位置的元素
p的列数是4,a的列数是5
着重理解指针类型的意义
ptr1指向aa[1][4]后面一个整形,ptr1-1指向aa[1][4]
ptr2指向aa[1][0],ptr2-1指向aa[0][4]
pa原本指向a[0],pa++后指向a[1],*pa得到a[1]的值即“at”的地址