C语言指针超详细讲解(3)

1. sizeof和strlen的对⽐?

1.1sizeof

讲解之前我们先来温习一个知识点:数组名的理解

数组名是首元素的地址但是有两个列外:

1. sizeof(数组名),这里的数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节。

2. &数组名,这里的数组名表示整个数组,&数组名取出的是数组的地址。

1.1 sizeof?
在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存内存空间⼤⼩的,单位是
字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩。
sizeof 只关注占⽤内存空间的⼤⼩,不在乎内存中存放什么数据。

我们使用代码为大家解释

#include<stdio.h>
int main()
{  
    //一维数组
    int a[]={ 1,2,3,4 }; //4个元素,每个元素是int类型(4个字节) 共16个字节
    printf(%d\n" ,sizeof(a)); 
// 数组名a单独放在sizeof内部,数组名表示整个数组,计算整个数组大小,共16个字节。
    printf(%d\n" ,sizeof(a+0)); 
// a并非单独放在sizeof内部,有没有&,所以数组名是数组首元素地址。(a+0)还是首元素地址,大小就是4/8 byte(取决于平台大小)
    printf(%d\n" ,sizeof(*a)); 
// a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址。 //*a就是 首元素(a首元素址,对a解引用就得到了a) //*a == a[0]
    printf(%d\n" ,sizeof(a+1));
// a并非单独放在sizeof内部,也没有&,所以数组名a是首元素地址,a+1就是第二个元素的地址 a+1 ==&a[1]
    printf(%d\n" ,sizeof(a[1]));
// 就是数组第二个元素,这里是计算第二个元素的大小,单位是字节-4
    printf(%d\n" ,sizeof(&a));
//  &a--是取出数组的地址,但是数组的地址也是地址,是地址就是 4/8个byte. //数组的地址  和   数组首元素地址 本质的区别是类型的区别,并非大小。
//a -- int*          int * p = a;
//&a -- int(*)[4]    int (*p)[4] = &a;
    printf(%d\n" ,sizeof(*&a));
//  对数组指针解引用访问一个数组的大小写,单位是字节。
    printf(%d\n" ,sizeof(&a+1));
//  &a是数组的地址,&a+1也是地址但是指向什么地方?我会在下面为大家画图解释。

解释一下sizeof(&a+1)。

我们在前面提到过数组指针类型    int (*p)[4] = &a; &a+1 跳过多少个字节取决于它的类型 数组

整形指针是四个字节所以&a+1跳过四个字节,指向4的位置。

以上是整形数组的相关知识,我们还有一些字符数组的知识需要了解。

关键点拨:指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节。

                  指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几字节。

                  在32位环境下,地址是32个二进制,需要4个字节,所以指针变量的大小就是4个字节.

                  在64位环境下,地址是64个二进制,需要8个字节,所以指针变量的大小就是8个字节.

                    

int main()
{ 
   //字符数组
   char arr[]={ 'a','b','c','d','e','f' }; //6
   printf("%d\n", sizeof(arr));
// 数组名单独放入sizeof内部,计算的是整个数组的大小单位是字节  6
   printf("%d\n", sizeof(arr+0));
// arr是首元素地址 == &arr[0] 是地址就是4/8个字节
   printf("%d\n", sizeof(*arr));
// arr数组名表示首元素地址  *arr就是首元素,大小就是1byte。
   printf("%d\n", sizeof(arr[1]));
// 就是第二个元素
   printf("%d\n", sizeof(&arr));
// &arr是数组的地址,sizeof(&arr)就是4/8个字节。
   printf("%d\n", sizeof(&arr+1));
// &arr+1 是指向f后面的那个元素的地址。

  

以上是一维数组,那如果是二维数组呢?

我们先来理解一下二维数组:二维数组可以理解为一维数组的数组。

假设访问第一个一维数组 a[ 0 ]  [ j ].

#include<stdio.h>
int main()
{
   int a[3][4]={ 0 };
   
   printf("%zd\n", sizeof(a));
// 48-a 数组名单独放在sizeof内部,表示整个数组,sizeof(a)计算的是数组的大小,单位是字节。
   printf("%zd\n", sizeof(a[0][0]));
// 4-a[0][0]是数组的第一行第一个元素,这里计算的就是第一个元素的大小,单位是字节。
   printf("%zd\n", sizeof(a[0]));
// a[0]是第一行这个一维数组的数组名,数组名单独放在了sizeof内部。
// a[0]就表示整个第一行这个一维数组,sizeof(a[0])计算的整个第一行这个数组的大小。
   printf("%zd\n", sizeof(*(a[0]+1));
//a[0]+1是第一行第二个元素的地址,*(a[0]+1)就是第一行第二个元素
   printf("%zd\n", sizeof(a[0]+1));
//a[0]并非单独放在sizeof内部,也没有&,所以a[0]表示第一行这个一维数组首元素的地址
//也就是第一行第一个元素的地址
//a[0]==&a[0][0]   
   printf("%zd\n", sizeof(a+1);
//a作为二维数组的数组名,并没有单独放在sizeof内部,也没有&,a就是数组首元素的地址,也就是第一行的地址
//a+1就是第二行的地址

   printf("%zd\n", sizeof(*(a+1));
//a+1是第二行的地址,*(a+1)就是第二行,计算的就是第二行的大小

  
  

  

我们来看一道面试题

该如何分析呢?

首先我们该明白(&a+1)是怎么回事?  其实在前面我们已经提到过了

因为&,取出的是整个数组的地址,所以跳过的是整个数组 。

那么我们不难得出

ptr 指向5后面的地方,ptr-1指向4和5之间,又因为是int类型,所以ptr-1就指向5.

 

以上是关于sizeof的相关知识,我们接下来为大家带来strlen相关知识。

1.2 strlen

strlen 求字符串长度

统计的是在字符串中\0之前出现字符的个数。

#include<stdio.h>
int main()
{
   //定义一个字符数组
   char arr[]={ 'a','b','c','d','e','f' };
   printf("%d\n", strlen(arr)); 
//arr是首元素地址
   printf("%d\n", strlen(arr+0));
//arr是首元素地址,arr+0还是首元素地址
   printf("%d\n", strlen(*arr));
//arr是首元素地址, *arr就是首元素 - ‘a’-97
//站在strlen的角度,认为传参进去的‘a'-97 就是地址。97作为地址,直接访问,就是非法访问。
   printf("%d\n", strlen(arr[1]));
//传参传进去的是‘b’,b是98作为地址也是非法访问。
   printf("%d\n", strlen(&arr));
//随机值
   printf("%d\n", strlen(&arr+1));
//随机值

因为没有\0(结束标志),所以是随机值。这个随机值是大于6的。

数组的内容到这里就结束了。

后面会持续更新结构体,字符串相关知识,请大家持续关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值