1.知识准备
数组和指针的定义:
数组和指针
数组 - 能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型
指针 - 地址/指针变量,大小是4/8个
数组和指针的关系:
数组是数组,指针是指针,二者不等价
1.数组名是数组首元素的地址,这个地址就可以存放在指针变量中
2.我们就可以使用指针变量来遍历数组
🚀数组名的注意事项:
1.通常情况:
大部分情况下数组名是数组首元素的地址
2.例外
1.sizeof(数组名) - 数组名表示整个数组,计算的是整个数组的大小
2.&数组名 - 数组名表示整个数组,取出的是数组的地址
2.指针和数组笔试题解析
注意:编译环境是x86环境!,sizeof是一个操作符,和+- * /类似
整型数组的sizeof
int a[]={1,2,3,4}的sizeof的使用
#include<stdio.h> int main(){ int a[] = {1,2,3,4}; printf("%d\n",sizeof(a));//1 printf("%d\n",sizeof(a+0));//2 printf("%d\n",sizeof(*a));//3 printf("%d\n",sizeof(a+1));//4 printf("%d\n",sizeof(a[1]));//5 printf("%d\n",sizeof(&a));//6 printf("%d\n",sizeof(*&a));//7 printf("%d\n",sizeof(&a+1));//8 printf("%d\n",sizeof(&a[0]));//9 printf("%d\n",sizeof(&a[0]+1))//10 return 0; }
接下来我将尽力解释每一行的含义
1.sizeof(a)
printf("%d\n", sizeof(a));
数组4个元素,每个元素是int类型,一个int类型4个字节, 4*4=16 byte
sizeof(a)就是数组名单独放在sizeof内部,计算的是数组的总大小, 单位是字节
运行结果:
2.sizeof(a + 0)
printf("%d\n",sizeof(a+0));
a+0,数组名(a)没有单独放在sizeof内部,这里属于参与运算变成地址了
||
a (首元素地址) + 0 == a(数组第一个元素地址) 这里并没有跳过任何距离,+0等于没加
所以大小为4个字节
运行结果:
3.sizeof(*a)
printf("%d\n", sizeof(*a))
a是数组首元素的地址 --> &a[0]
*a -> *&a[0] -> a[0] ==> * 和 & 可以互相抵消
个人理解:
因为a是数组首元素的地址,可以写成&a[0],即*a==*&a[0],所以*a可以表示为: *&a[0]
整体思想:
&a[0]是取出这个元素所在的内存空间的对应唯一的地址,而 *地址,是对地址解引用,找到那块空间对应的元素,而数组a的类型是int,所以它每个元素的数据类型也是int,所占内存空间字节是4 byte ,所以打印的结果为4
运行结果:
4.sizeof(a + 1)
a是数组首元素的地址 -- int* ,a+1 跳过一个整型,是第二个元素的地址
运行结果:
5.sizeof(a[1])
a[1]表示数组第二个元素,一个int大小就是4/8个字节
运行结果:
6.sizeof(&a)
&a - 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4/8个字节
&a存起来:
int (*pa)[4]= &a --> 去掉pa,该指针类型为int (*)[4]
运行结果:
7.sizeof(*&a)
* 和 & 可以互相抵消,所以*&a==a,等于没有操作
个人理解:当对指针解引用的时候,访问几个字节取决于指针的类型
当是一个整型指针的时候,解引用访问的是一个整型,
当是一个字符指针的时候,解引用访问的是一个字符,
当是一个数组指针的时候,解引用访问的是一个数组,a[4],其类型是int,有4个元素,所以大小为16byte
运行结果:
8. sizeof(&a + 1)
优先级是靠近的先算&a,先取地址,再解引用,跟优先级无关
区别:
数组名取地址取到的是整个数组的地址,从值上来看整个数组的地址和数组首元素地址的值相同,区别就是数组首元素地址+1时,跳过一个元素,整个数组地址+1时,跳过整个数组
&a+1 地址跳过一个数组,还是指向内存里面的,是地址就是4/8个byte
&a[0]是取出数组首元素地址 <==> &a是数组的地址
注意:
&a[0]和a(数组名)是等价的
运行结果:
图解:
9.sizeof(&a[0] )
数组第一个元素的地址
运行结果:
10.sizeof(&a[0] + 1)
数组第二个元素的地址
运行结果:
字符数组的sizeof和strlen
char arr[]={'a','b','c','d','e','f'}的sizeof的使用
预备知识:
1.sizeof计算的是占用内存空间的大小,单位是字节,不关注内存中到底存放的是什么
2.sizeof不是函数,是操作符
3.strlen是函数
4.strlen是针对字符串的,求的是字符串的长度,本质上是统计 \0 之前出现的字符个数
//字符数组 #include<string.h> int main() { char arr[] = { 'a','b','c','d','e','f'}; printf("%d\n", sizeof(arr));//6 printf("%d\n", sizeof(arr + 0));//arr+0是数组首元素地址 printf("%d\n", sizeof(*arr));//*arr是首元素的,计算的是首元素的大小 printf("%d\n", sizeof(arr[1]));//1 printf("%d\n", sizeof(&arr));//&arr是数组的地址 4/8 printf("%d\n", sizeof(&arr + 1));//&arr + 1跳过一个数组后的地址 4/8 printf("%d\n", sizeof(&arr[0] + 1));//4/8 第二个元素的地址 return 0; }
1.sizeof(arr)
数组名单独放在sizeof()内部,是数组的地址,这个数组是没有放'\0'的,所以仅仅只有6个元素,所以计算的是整个数组的大小,为6byte
运行结果:
2.sizeof(arr + 0)
数组名arr,没有单独放在sizeof()内部,arr+0就是数组首元素地址是地址字节大小就是4/8byte
运行结果:
3.sizeof(*arr)
*arr是首元素,计算的是首元素的大小,而一个char类型大小就1byte
运行结果:
4.sizeof(arr[1])
char类型数组第二个元素,字节大小是1byte
运行结果:
5.sizeof(&arr)
&arr,是取出char a数组的地址,是地址大小就是4/8byte
运行结果:
6.sizeof(&arr + 1)
&arr + 1跳过一个数组后的地址,字节大小是4/8
运行结果:
7.sizeof(&arr[0] + 1)
字符数组第二个元素的地址,字节大小是4/8
运行结果: