今天,咱来唠唠一个困扰很多小伙伴儿的问题——“sizeof和strlen在数组中的应用”。
首先,让我们来回忆一下sizeof和strlen的概念哈。
目录
一、用法与参数
-
sizeof:
- 可以用类型做参数,如
sizeof(int)
、sizeof(float)
等。 - 也可以用表达式或对象做参数,如
sizeof(i)
(其中i为变量名)、sizeof array
(其中array为数组名)等。 - 还可以对函数调用求值,但结果是函数返回类型的大小,函数并不会被调用,如
sizeof(foo())
(其中foo为函数名)。
- 可以用类型做参数,如
-
strlen:
- 只能用
char*
(字符指针)做参数,且该字符串必须是以'\0'
结尾的。 - 传递给strlen的数组名会退化成指针,因此无法直接通过strlen获取数组的总大小(包括所有元素和可能的结束符)。
- 只能用
-
sizeof:
- 功能是获取对象或类型所占的内存字节数。(包括结束符
'\0'
) - 返回值是对象或类型所占的内存字节数,是一个编译时常量。
- 功能是获取对象或类型所占的内存字节数。(包括结束符
-
strlen:
- 功能是计算字符串的长度(不包括结束符
'\0'
)。 - 返回值是字符串的长度,是一个运行时的计算结果。
- 功能是计算字符串的长度(不包括结束符
现在,让咱们来聊聊它俩在一维数组中的应用。
二、大闯关
(一)int怪
开始打怪吧(ง •_•)ง
咱先来看看以下int型代码,如果不运行,你能算出来它们的值不?
int a[] = {1,2,3};
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));
是不是又很多小伙伴,已近懵了。不过,没关系。看了我的解释,相信大伙儿,都能理解的哦。
tips:数组名:表示数组首元素地址,除了两种情况以外。
1.&数组名:数组名表示整个数组,取出整个数组地址。
2.sizeof(数组名):数组名表示整个数组,计算整个数组大小。
int a[] = {1,2,3}; //a[]实际上放的是“1,2,3” 3个元素
printf("%d\n",sizeof(a));运行结果:12 解释:a表示整个数组,其类型是 int(4个字节),
sizeof(a)计算整个数组大小3*4=12。
printf("%d\n",sizeof(a+0));运行结果:4/8(32位/64位) 解释:a + 0
表示数组 第一个元素的地址 ,
其类型是 int,
sizeof(a+0)计算地址大小。
printf("%d\n",sizeof(*a));运行结果:4解释:*a表示数组的第一个元素,int类型(4个字节),sizeof(*a)计算元素大小。
printf("%d\n",sizeof(a+1));运行结果:4/8解释:a + 1
表示数组 第二个元素的地址,其类型也是 int
。sizeof(a+1)计算地址大小 。
printf("%d\n",sizeof(a[1]));运行结果:4解释:a[1]
表示数组第二个元素,其类型是 int*,
sizeof(a[1])计算元素大小。
printf("%d\n",sizeof(&a));运行结果:4/8解释:&a
表示整个数组a的地址,但是本质也是地址,sizeof(&a)
表示地址大小。
printf("%d\n",sizeof(*&a));运行结果:12解释:*&a
表示整个数组a的元素。sizeof(*&a)
计算整个数组a的元素的大小。
printf("%d\n",sizeof(&a+1));运行结果:4/8解释:&a + 1
表示整个a数组后面空间的数组地址。sizeof(&a+1)计算地址大小。
printf("%d\n",sizeof(&a[0]));运行结果:4/8解释:&a[0]
表示数组 a第一个元素的地址 ,sizeof(&a+1)计算地址大小。
printf("%d\n",sizeof(&a[0]+1));运行结果:4/8解释:&a[0]+1
表示数组 a第二个元素的地址 ,sizeof(&a[0]+1)计算地址大小。
(二)char 怪
小怪一
看它好像不是很厉害,快来打败它。
char arr[] = {'a','b','c','d'};
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = {'a','b','c','d'}; //a[]实际上放的是“a,b,c,d” 4个元素
printf("%d\n", sizeof(arr));运行结果:4解释:arr
数组名在这里是第二种特殊情况,表示整个数组元素,类型是 char(1个字节),sizeof(arr)计算整个数组大小4*1=4。
printf("%d\n", sizeof(arr+0));运行结果:4/8解释:arr+0
表示第一个数组元素地址,sizeof(arr+0)计算地址大小。
printf("%d\n", sizeof(*arr));运行结果:1解释:*arr
表示第一个数组元素,类型为char(1个字节),sizeof(*arr)计算元素大小。
printf("%d\n", sizeof(arr[1]));运行结果:1解释:*arr
表示第一个数组元素,类型为char(1个字节),sizeof(*arr)计算元素大小。
printf("%d\n", sizeof(&arr));运行结果:4/8解释:&arr是第一种特例,
表示整个素数组地址,sizeof(&arr)计算地址大小。
printf("%d\n", sizeof(&arr+1));运行结果:4/8解释:&arr
表示数组arr后面一个空间数组地址,sizeof(&arr+1)计算地址大小。
printf("%d\n", sizeof(&arr[0]+1));运行结果:4/8解释:&arr[0]+1,
表示第二个素数组地址, sizeof(&arr[0]+1)计算地址大小。
printf("%d\n", strlen(arr));运行结果:随机 解释:arr,
表示首素数组地址, strlen(arr)计算从数组arr首元素向后一直到'\0'(不包括'\0')的字符串长度。
printf("%d\n", strlen(arr+0));运行结果:随机 解释:arr+0,
表示首素数组地址, strlen(arr+0)计算从数组arr首元素向后一直到'\0'(不包括'\0')的字符串长度。
printf("%d\n", strlen(*arr));运行结果:错误 解释:*arr,
表示数组arr首元素, strlen(*arr)计算'a'所代表的‘97’的字符串长度,而这里的‘97’不是地址量,会出错。
printf("%d\n", strlen(arr[1]));运行结果:错误 解释:arr[1],
表示数组arr首元素, strlen(arr[1])计算'a'所代表的‘97’的字符串长度,而这里的‘97’不是地址量,会出错。
printf("%d\n", strlen(&arr));运行结果:随机 解释:&arr,
表示整个数组arr地址,这里相当于上面的arr+0,
strlen(&arr)计算从数组arr的首元素向后一直到'\0'(不包括'\0')的字符串长度。
printf("%d\n", strlen(&arr+1));运行结果:随机(比上面的随机值小4) 解释:&arr+1,
表示arr后面空间的数组首地址, strlen(&arr+1)计算从数组arr的最后一个元素向后一直到'\0'(不包括'\0')的字符串长度。
printf("%d\n", strlen(&arr[0]+1));运行结果:随机(比上面的随机值大3) 解释:&arr[0]+1,
表示arr的第二个元素的地址, strlen(&arr[0]+1)计算从数组arr的第二个元素向后一直到'\0'(不包括'\0')的字符串长度。
小怪二
这只怪兽好像还行,快去挑战看看。
char arr[] = "abcd";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
char arr[] = "abcd"; //a[]实际上放的是“ a,b,c,d,\0 ” 5个元素
printf("%d\n", sizeof(arr));运行结果:5 (解释与上面相似,不再解释。)
printf("%d\n", sizeof(arr+0));运行结果:4/8
printf("%d\n", sizeof(*arr));运行结果:1
printf("%d\n", sizeof(arr[1]));运行结果:1
printf("%d\n", sizeof(&arr));运行结果:4/8
printf("%d\n", sizeof(&arr+1));运行结果:4/8
printf("%d\n", sizeof(&arr[0]+1));运行结果:4/8
printf("%d\n", strlen(arr));运行结果:4
printf("%d\n", strlen(arr+0));运行结果:4
printf("%d\n", strlen(*arr));运行结果:错误
printf("%d\n", strlen(arr[1]));运行结果:错误
printf("%d\n", strlen(&arr));运行结果:4
printf("%d\n", strlen(&arr+1));运行结果:随机
printf("%d\n", strlen(&arr[0]+1));运行结果:3
(三)指针怪
这是最后一只,加油💪💪💪
char *p = "abcd";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
char *p = "abcd"; //在内存中开辟一个空间,存放“ a,b,c,d,\0 ” 5个元素,p指向a的地址
printf("%d\n", sizeof(p));运行结果:4/8 解释:p
表示a的地址,sizeof(p)计算地址大小。
printf("%d\n", sizeof(p+1));运行结果:4/8 解释:p+1
表示b的地址,sizeof(p)计算地址大小。
printf("%d\n", sizeof(*p));运行结果:1 解释:*p
表示a,a为char型,sizeof(*p)计算元素a大小。
printf("%d\n", sizeof(p[0]));运行结果:1解释:p[0]
表示a,a为char型,sizeof(p[0])计算元素a大小。
printf("%d\n", sizeof(&p));运行结果:4/8 解释:&p
表示整个空间p的地址,本质上还是地址,sizeof(&p)计算地址大小。
printf("%d\n", sizeof(&p+1));运行结果:4/8 解释:&p+1
表示整个空间p后面空间的首元素地址,本质上也还是地址,sizeof(&p)计算地址大小。
printf("%d\n", sizeof(&p[0]+1));运行结果:4/8 解释:&p[0]+1
表示b的地址,sizeof(&p[0]+1)计算地址大小。
printf("%d\n", strlen(p));运行结果:4 解释:p
表示a的地址,strlen(p)计算从a向后一直到'\0'的字符串长度。
printf("%d\n", strlen(p+1));运行结果:3 解释:p
表示b的地址,strlen(p)计算从b向后一直到'\0'的字符串长度。
printf("%d\n", strlen(*p));运行结果:错误 解释:*p
表示元素a,表示‘97’,不是字符类型,strlen(*p)会出错。
printf("%d\n", strlen(p[0]));运行结果:错误 解释:p[0]
表示元素a,表示‘97’,不是字符类型,strlen(p[0])会出错。
printf("%d\n", strlen(&p));运行结果:随机 解释:&p
表示整个空间p的地址,可是咱们并不清楚p空间内部是什么情况,strlen(&p)计算从p首元素向后一直到'\0'的字符串长度。
printf("%d\n", strlen(&p+1));运行结果:随机 解释:&p+1
表示整个空间p,后面空间首元素的地址,可是咱们并不清楚后面空间内部是什么情况,strlen(&p+1)计算从后面空间首元素向后一直到'\0'的字符串长度。
printf("%d\n", strlen(&p[0]+1));运行结果:3 解释:&p[0]+1
表示b的地址,strlen(&p[0]+1)计算从b向后一直到'\0'的字符串长度。
注意啦,上面的解释是为了大伙儿便于理解,若是有专业性错误,还望咱们打怪战士指出。
希望大伙儿通过今天的学习,可以轻轻松松搞定sizeof和strlen在一维数组中的小怪兽们。
最后,别忘了一健三连哦。