深入了解指针和数组

一、sizeof和strlen

1.sizeof 操作符

sizeof实际上是一个操作符:
sizeof(表达式),表达式不参与运算,sizeof计算的是表达式最终占空间的字节的大小,计算的是字节,表达式也可以是某个变量的类型

sizeof计算的是表达式所占字节的大小

int a = 0;
printf("%d\n",sizeof(a));//这里sizeof计算的是a的大小是4个字节
printf("%d\n",sizeof(int));//这里sizeof计算的是一个整型的大小是4个字节

sizeof(表达式),表达式不参与运算

int a = 5;
int c = 10;
printf("%d\n",sizeof(c = a + 1));//这里sizeof计算的是c的大小,c是一个整数,占4个字节
//c在sizeof内部表达式中被赋给了a+1的值,但sizeof中的表达式是不参与运算的
printf("%d\n",c);//最终打印出的c的值还是10

2.strlen库函数

strlen是c语言库中自带的库函数:
strlen本质上是判断字符串的长度,传给strlen一段字符串,strlen会计算字符串中’\0’前有多少个字符来计算整个字符串的长度,其中空格也会被计算。
它的关键是找字符串中的’\0’,如果没有找到,他就会越界,直到找到’\0’为止,此时他就会返回一个随机值


在这里插入图片描述


举个栗子:
strlen使用方式:

char arr1[20] = "I am strlen!";//字母、空格、符号总共加起来有12个字符,
                               //这个字符串长度为12
printf("%d\n",strlen(arr1));//通过strlen打印出来的结果也是12

找不到‘\0’时:

char arr[] = { 'a','b','c','d','e','f' };//这是一个字符数组,存放了6个字符,没有'\0'
printf("%d\n", strlen(arr));//这时如果想要通过strlen计算长度,
//它会从第一个元素的地址开始计算,找到数组最后一个字符时,仍然没有找到'\0',
//它会继续往后找,直到找到'\0',返回的就是一个随机值

二、sizeof和数组的联系


数组名的意义
只有当sizeof(数组名)和&数组名,数组名表示整个数组,其他任何出现数组名的地方都表示数组首元素地址。


在这里深入了解一下sizeof和数组结合后会有哪些不同的意义:
1.sizeof(数组名),这里的数组名表示的是计算整个数组的大小
2.sizeof(数组名+数字),这里的数组名是数组首元素的地址,sizeof计算的是数组下标为该数字的地址,而地址就是指针的大小,根据不同的编译器(x86/x64)下,最终结果为4/8
3.sizeof(&数组名),数组名前加了取地址运算符,这个数组就表示整个数组,取出的也是整个数组的地址,是地址就是指针类型,返回的就是4/8。


三、指针和数组的一些练习

1.一维数组

下面每个数组都是基于如下一维数组a
int a[] = { 1,2,3,4 };

subject_1:

printf("%d\n", sizeof(a));//输出为16

在这里插入图片描述


sizeof(数组名),数组名表示整个数组的大小,这里计算的就是整个数组的大小占多少字节
数组中每个元素都是整型,也就是每个元素都占4个字节,总共4个元素,占4*4=16个字节

subject_2:

printf("%d\n", sizeof(a + 0));//输出为4/8

在这里插入图片描述


sizeof(a+0),中a表示数组首元素地址,+0后还是数组首元素地址,地址计算出的就是4/8个字节。

subject_3:

printf("%d\n", sizeof(*a));//输出为4,表示一个整数的大小是4个字节

在这里插入图片描述


数组a没有单独和sizeof放一块,a表示数组首元素地址,而*a就是对数组首元素地址进行解引用,得到的是数组的第一个元素1,1是整型,所以它的大小就是4个字节。

subject_4:

printf("%d\n", sizeof(a + 1));//输出为4/8

在这里插入图片描述


数组a没有和sizeof单独放一块,a表示数组首元素地址,a+1表示的就是数组下标为1的地址,sizeof(a+1)计算的是地址的大小,为4/8个字节。

subject_5:

printf("%d\n", sizeof(a[1]));//输出为4

在这里插入图片描述


很明显,a[1]就是数组第二个元素,sizeof(a[1])就是sizeof(2),大小是4个字节。

subject_6:

printf("%d\n", sizeof(&a));//输出为4/8

在这里插入图片描述


这里对数组进行了&操作,a就表示整个数组,取出的也是整个数组的地址,sizeof计算的就是整个数组的地址的大小,为4/8个字节。

subject_7:

printf("%d\n", sizeof(*&a));//输出为16

在这里插入图片描述


数组a首先进行&操作,取出了整个数组的地址,然后对该地址进行解引用操作,最终得到的就是整个数组的元素,sizeof(*&a)计算的是数组a中全部元素的大小,应为4 * 4 = 16个字节。

subject_8:

printf("%d\n", sizeof(&a + 1));//输出为4/8

在这里插入图片描述


数组a首先进行&操作,取出了整个数组的地址,然后进行+1跳过的就是整个数组,最终指向的是相当于整个数组的地址,sizeof(&a+1)计算的就是整个数组的地址,为4/8个字节。

subject_9:

printf("%d\n", sizeof(&a[0]));//输出为4/8

在这里插入图片描述


这里可以看出计算的是a[0]的地址的大小,也就是数组的第一个元素的地址的大小,是地址,结果就是4/8个字节。

subject_10:

printf("%d\n", sizeof(&a[0] + 1));//输出为4/8

在这里插入图片描述


先对a[0]进行&操作,得到第一个元素的地址,然后进行+1得到的就是第二个元素的地址,sizeof(&a[0]+1)计算的就是第二个元素的地址的大小就是4/8个字节。


2.字符数组

(1)sizeof与字符数组

sizeof计算的是占多大的字节
以下每个数组都是基于如下字符数组:
char arr[] = { 'a','b','c','d','e','f' };

subject_1:

printf("%d\n", sizeof(arr));//输出为6

在这里插入图片描述


arr数组名单独与sizeof放一块,表示整个数组的大小,计算的是整个数组的大小,其中1个字符为1个字节,共6个字符,大小就是6 * 1 = 6个字节。

subject_2:

printf("%d\n", sizeof(arr + 0));//输出为4/8

在这里插入图片描述


arr数组没有跟sizeof单独放一块,表示的就是数组首元素地址,+0操作后还是首元素地址,地址的大小就是4/8个字节。

subject_3:

printf("%d\n", sizeof(*arr));//输出为1

在这里插入图片描述


这里对arr进行解引用,arr表示的是数组首元素地址,解引用后就是数组首元素‘a’,sizeof(*arr)计算的是字符‘a’的大小,为1个字节。

subject_4:

printf("%d\n", sizeof(arr[1]));//输出为1

在这里插入图片描述


arr[1]就是数组第二个元素,sizeof(arr[1])计算的是字符’b’的大小,为1个字节。

subject_5:

printf("%d\n", sizeof(&arr));//输出为4/8

在这里插入图片描述


arr进行&操作,拿到的是整个数组的地址,sizeof(&arr)计算的就是数组的整个地址的大小,为4/8个字节。
subject_6:

printf("%d\n", sizeof(&arr + 1));//输出为4/8

在这里插入图片描述


&arr取出的是整个数组的地址,+1操作后跳过的是整个数组,指向的还是一个地址,这个地址也是相当于整个数组的地址。

subject_7:

printf("%d\n", sizeof(&arr[0] + 1));//输出为4/8

在这里插入图片描述


首先&arr[0]得到的是arr[0]的地址,就是第一个元素的地址,+1跳过一个元素的大小,指向了第二个元素的地址,sizeof(&arr[0]+1)计算的是第二个元素的地址的大小,为4/8个字节。


以下每个数组都是基于如下数组字符串:
char arr[] = "abcdef";

subject_1:

printf("%d\n", sizeof(arr));//输出为7

在这里插入图片描述


sizeof单独与arr放一块,计算的是整个数组的大小,数组中存放的是"abcdef\0",加上’\0’在内共有7个字符的字符串,它所占的大小就是7个字节。

subject_2:

printf("%d\n", sizeof(arr + 0));//输出为4/8

在这里插入图片描述


arr没有跟sizeof单独放一块,所以这里的arr+0拿到的就是数组首元素的地址,计算的也是数组首元素地址的大小为4/8个字节。

subject_3:

printf("%d\n", sizeof(*arr));//输出为1

在这里插入图片描述


arr没有跟sizeof单独放一块,arr表示数组首元素地址,解引用后就是数组第一个元素,sizeof(*arr)计算的是第一个数组元素的的大小为1个字节。

subject_4:

printf("%d\n", sizeof(arr[1]));//输出为1

在这里插入图片描述


arr[1]就是数组第二个元素,它的大小就是1个字节

subject_5:

printf("%d\n", sizeof(&arr));//输出为4/8

在这里插入图片描述


arr进行&操作得到整个数组的地址,sizeof(&arr)计算的是整个数组的地址的大小为4/8个字节。

subject_6:

printf("%d\n", sizeof(&arr + 1));//输出为4/8

在这里插入图片描述


arr先进行&操作得到整个数组的地址,然后+1跳过整个数组,指向下一个地址,sizeof(&arr+1)计算的是整个数组地址的大小为4/8个字节。

subject_7:

printf("%d\n", sizeof(&arr[0] + 1));//输出为4/8

在这里插入图片描述


arr[0]是第一个元素,对它&操作后得到第一个元素的地址,再+1得到了第二个元素的地址,sizeof(&arr[0]+1)计算的是第二个元素的地址的大小为4/8个字节。

(2)strlen与字符数组

strlen计算的是字符串的长度,strlen接收一个地址,然后通过找’\0’来计算字符串长度

以下每个数组都是基于如下字符数组:
char arr[] = { 'a','b','c','d','e','f' };

subject_1:

printf("%d\n", strlen(arr));//输出随机数

在这里插入图片描述


strlen接收arr数组首元素地址,也就是从字符’a’开始,向后找’\0’,而该数组中没有’\0’,当找完整个数组后,会越界继续往后找,直到遇到一个’\0’,返回一个随机值。

subject_2:

printf("%d\n", strlen(arr + 0));//输出随机值

在这里插入图片描述


arr+0后指向的就是数组首元素地址,strlen接收该地址,向后找\0,会越界往后找,无法确定\0在内存中的位置,输出的就是随机值。

subject_3:

printf("%d\n", strlen(*arr));//非法访问

在这里插入图片描述


对arr进行解引用得到字符’a’,而strlen接收的是一个地址,strlen会把字符’a’当作一个地址去访问,字符’a’的ASSIC码值为97,strlen就会访问地址为97的空间,造成非法访问。

subject_4:

printf("%d\n", strlen(arr[1]));//非法访问

在这里插入图片描述


arr[1]就是字符’b’,strlen会将字符’b’当作地址进行访问,字符’b’的ASSIC码值为98,直接访问就会造成非法访问的异常。

subject_5:

printf("%d\n", strlen(&arr));//输出随机值

在这里插入图片描述


arr进行&操作得到的是整个数组的地址,strlen接收的是整个数组的地址,也是从首元素’a’开始,往后找’\0’,数组内没有’\0’,会继续往后越界找’\0’,返回的是随机值。

subject_6:

printf("%d\n", strlen(&arr + 1));//输出随机值

在这里插入图片描述


&arr得到的是整个数组的地址,+1后跳过整个数组,指向的是跳过整个数组后的地址,strlen接收的是跳过整个数组后的地址,从该地址往后找\0,返回一个随机值。

subject_7:

printf("%d\n", strlen(&arr[0] + 1));//返回随机值

在这里插入图片描述


arr[0]是数组首元素,对它进行&操作,得到首元素地址,+1跳过一个字节的大小得到第二个元素的地址,strlen接收这个地址,往后找’\0’,会越界直到找到’\0’为止,返回一个随机值。


以下每个数组都是基于如下数组:
char arr[] = "abcdef";

subject_1:

printf("%d\n", strlen(arr));//输出6

在这里插入图片描述


arr就是数组首元素地址,strlen接收该地址从字符’a’往后找’\0’,这个字符数组存放的就是字符串,最后有’\0’,‘\0’之前有6个字符,最后输出6。

subject_2:

printf("%d\n", strlen(arr + 0));//返回6

在这里插入图片描述


arr是数组首元素地址,arr+0还是数组首元素地址,strlen接收的就是数组首元素地址,计算的是数组内字符串的长度,为6。

subject_3:

printf("%d\n", strlen(*arr));//非法访问

在这里插入图片描述


这里对arr进行解引用得到的还是字符’a’,字符’a’的ASSIC码值是97,将97作为地址进行访问会发生异常。

subject_4:

printf("%d\n", strlen(arr[1]));//非法访问

在这里插入图片描述


arr[1]就是字符’b’,strlen会将字符’b’当作地址进行访问,字符’b’的ASSIC码值为98,直接访问就会造成非法访问的异常。

subject_5:

printf("%d\n", strlen(&arr));//6

在这里插入图片描述


&arr拿到的是整个数组的地址,strlen接收的是数组的地址,计算的还是字符串的长度为6。

subject_6:

printf("%d\n", strlen(&arr + 1));//输出随机值

在这里插入图片描述


&arr得到的是整个数组的地址,+1后跳过整个数组,strlen接收到的是跳过整个数组后的地址,从这个地址开始往后找’\0’,直到找到为止,返回的是随机值。

subject_7:

printf("%d\n", strlen(&arr[0] + 1));//输出5

在这里插入图片描述


arr[0]取地址得到的是第一个元素的地址,+1就是第二个元素的地址,从第二个字符开始往后找\0,字符串的长度就是5。

3.字符指针

(1)sizeof与字符指针

如下字符指针:
char *p = "abcdef";

subject_1:

printf("%d\n", sizeof(p));//输出4/8

在这里插入图片描述


p是指针类型,sizeof( p )计算的就是指针的大小,为4/8个字节。

subject_2:

printf("%d\n", sizeof(p + 1));//输出4

在这里插入图片描述


p是cahr*类型的指针,p+1跳过的是一个字节的地址,还是指针类型,大小为4/8个字节。

subject_3:

printf("%d\n", sizeof(*p));//输出1

在这里插入图片描述


p指向的是字符串首元素地址,对p解引用得到的是字符串第一个字符,一个字符占1个字节。

subject_4:

printf("%d\n", sizeof(p[0]));//输出1

在这里插入图片描述


p是指针,p[0]就相当于*(p+0),得到的还是字符串第一个字符,大小占1个字节。

subject_5:

printf("%d\n", sizeof(&p));//输出4/8

在这里插入图片描述


p指向的本身就是一个地址,&p得到的就是地址的地址,计算的还是地址的大小,为4/8个字节。

subject_6:

printf("%d\n", sizeof(&p + 1));//输出4/8

在这里插入图片描述


对p进行&操作后,是将&p放到了一个char的二级指针中,而&p+1跳过的是一个char的大小,指向的还是一块地址,地址的大小就是4/8个字节。

subject_7:

printf("%d\n", sizeof(&p[0] + 1));//输出4/8

在这里插入图片描述


p[0]表示的是字符串第一个字符,对它&后+1得到的就是第二个字符的地址,大小占4/8个字节。

(2)strlen与字符指针

如下字符指针:
char *p = "abcdef";

subject_1:

printf("%d\n", strlen(p));//输出6

在这里插入图片描述


p指向的是字符串的第一个字符的地址,strlen接收这个地址往后找\0,返回这个字符串的长度是6。

subject_2:

printf("%d\n", strlen(p + 1));//输出5

在这里插入图片描述


p+1指向的是字符串第二个字符的地址,strlen接收这个地址,从第二个字符开始往后找’\0’,字符串的长度就是5。

subject_3:

printf("%d\n", strlen(*p));//非法访问

在这里插入图片描述


对p进行解引用得到第一个字符’a’,strlen会将字符’a’当作一个地址访问,造成非法访问的异常。

subject_4:

printf("%d\n", strlen(p[0]));//非法访问,p[0]就相当于*(p+0)

在这里插入图片描述


p[0]就是字符串第一个元素’a’,strlen会将字符’a’当作一个地址访问,造成非法访问的异常。

subject_5:

printf("%d\n", strlen(&p));//随机值

在这里插入图片描述


&p是将char*类型的指针p的地址存放在char**的指针中,strlen接收这块地址,往后找\0,返回就是随机值。

subject_6:

printf("%d\n", strlen(&p + 1));//随机值

在这里插入图片描述


&p是将char*类型的指针p的地址存放在char**的指针中,在进行+1操作跳过char **的大小,指向的还是一块地址,strlen接收这块地址,往后找\0,返回就是随机值。

subject_7:

printf("%d\n", strlen(&p[0] + 1));//输出5

在这里插入图片描述


p[0]是字符串第一个字符‘a’,对它&后得到它的地址,+1得到的就是字符’b’的地址,strlen接收这个地址,往后找\0,返回字符串的长度是5。


到这里,关于指针和数组的深入了解就告一段落啦,蟹蟹大家的支持,欢迎回访!!!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叶落闲庭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值