C语言 -- sizeof操作符与strlen库函数的用法与比较

前言:

sizeof是操作符,strlen是库函数。虽然定义简单,但是有很多需要注意的知识点...

目录:

  一、sizeof操作符

  二、strlen库函数

  三、sizeof与strlen的比较(其实就是字符数组和字符串数组的比较)

  四、练习总结

         1. 整型数组中sizeof的案例

         2. 字符数组中的sizeof计算

3. 字符数组中的strlen计算

4. 字符串数组中的sizeof计算

5. 字符串数组中的strlen计算

6. 字符串指针中的sizeof计算

         sizeof与strlen总结:


  一、sizeof操作符

sizeof  返回变量或类型占用的内存量(以字节为单位),它与变量的值无关

注意事项:

  ”与变量的值无关“ -- sizeof()不会计算括号内部的表达式

 如图案例所示:假设有第五行的数组,此时第五行数组的大小是4*4=16,sizeof操作符()内部不参与实际运算,所以实际上没有去越界访问。

  sizeof是关键字,是在编译阶段处理的

   也就是说你程序没有运行前,sizeof(arr)就被替换成了一个固定的常量,保存在了test.out中了。你可以试试这样写 sizeof ptr也是不会报错的,这也说明了sizeof不是函数。

   如图案例所示:如果sizeof内部是一个表达式,首先sizeof并不会对括号内部的表达式进行计算,并且sizeof是再编译期间将表达式替换成固定的常量4,所以返回内存量是4个字节。

  当在用户自定义的类型上使用时,sizeof仍然返回该类型的实例使用的内存量,但值得指出的是,这并不一定等于其成员的总和

如图案例:因为自定义结构体存在内存对齐,所以实际占用的内存量是对齐后的结果12。明显不是成员的总和,总和的话是简单的相加4+1+4=9。

  计算数组大小

  由于数组名的特殊性,sizeof计算数组大小的时候,要特别区分计算的是整个数组的大小,还是一个数组数据类型的大小。

只有数组名arr单独放在sizeof内部,即sizeof(arr)的时候,计算的才是整个数组的大小

sizeof的计算大致有三种情况:

(1)计算变量大小

(2)计算数据类型的大小

在变量上使用 <==> 等同于在变量的数据类型上使用

(3)计算数组的大小

二、strlen库函数

strlen 求字符串长度  --   单位是字节 (如果不是字符串,可能会出现错误) 

注意事项:

① strlen函数内部实现:计算从字符串起始地址开始,到末尾的结束标志'\0'结束。                     也就是说,strlen的计算依赖于末尾的结束标志'\0'。

② 库函数使用时,记得引头文件

代码示例:

三、sizeof与strlen的比较

两者的比较基于:字符数组和字符串数组

字符数组末尾不自带结束标志'\0',字符串数组末尾自带结束标志。

解释:

  sizeof计算内存量。计算数组时,如果数组名单独放在其中,计算整个数组大小

sizeof(arr1)=3:因为arr1中只有三个字符,占三个字节大小;

sizeof(arr2)=4:因为arr2中,由于字符末尾自动带’0‘。'\0'也算一个字符,占用一个字节空间。所以sizef (arr2)=3+1=4。

  strlen计算依赖结束标志'\0'

strlen(arr1)=随机值19:arr1中末尾没有结束标志,此时程序一直往后读,直到找到0。什么时候找到0是不确定的,所以是随机值19;

strlen(arr2)=字符串长度3:arr2中,有结束标志0。但值得注意的是,strlen并不会将结束标志计入长度。

四、练习总结

 1. 整型数组中sizeof的案例

#include<stdio.h>
int main()
{
	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));
	return 0;
}

详解 :

#include<stdio.h>
int main()
{
	int a[] = { 1,2,3,4 };   
	printf("%d\n", sizeof(a));        //4*4=16,a单独放在sizeof内部,计算整个数组的大小
	printf("%d\n", sizeof(a + 0));    //4/8,a没有单独放在sizeof内部,就是它原本的意思--数组首元素地址
	printf("%d\n", sizeof(*a));       //4,解引用首元素地址--首元素的值。值是int型,占用内存4个字节
	printf("%d\n", sizeof(a + 1));    //4/8,数组第二个元素的地址。只要是地址,占用内存大小就是4或者8
	printf("%d\n", sizeof(a[1]));     //4,数组第二个元素的值,int类型,4个字节
	printf("%d\n", sizeof(&a));       //4/8,整个数组的地址,是地址,占用内存都是4或8
	printf("%d\n", sizeof(*&a));      //4*4=16,相当于a,a单独放在sizeof内部,求的是整个数组的大小
	printf("%d\n", sizeof(&a + 1));   //4/8,跳过整个数组后,接着的那个地址
	printf("%d\n", sizeof(&a[0]));    //4/8,数组首元素的地址
	printf("%d\n", sizeof(&a[0] + 1));//4/8,数组第二个元素的地址
	return 0;
}

 2. 字符数组中的sizeof计算

#include<stdio.h>
int main()
{
	char arr[] = { 'a ', 'b', 'c', 'd', 'e', 'f' };
	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));
    return 0;
}

详解:

#include<stdio.h>
int main()
{
	char arr[] = { 'a ', 'b', 'c', 'd', 'e', 'f' };
	printf("%d \n", sizeof(arr));        //6,arr单独放在sizeof内部,求整个数组的大小
	printf("%d\n", sizeof(arr + 0));     //4/8,arr不单独,表首元素地址 
	printf("%d\n", sizeof(*arr));        //1,*(数组首元素地址)->数组首元素的值
	printf("%d\n", sizeof(arr[1]));      //1,数组第二个元素的值
	printf("%d\n", sizeof(&arr));        //4/8,&arr整个数组的地址,但在数值上等于arr
	printf("%d\n", sizeof(&arr + 1));    //4/8,跳过一整个数组后接着的地址
	printf("%d \n", sizeof(&arr[0] + 1));//4/8,数组第二个元素的地址
	return 0;
}

 

3. 字符数组中的strlen计算

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a ', 'b', 'c', 'd', 'e', 'f' };
    printf("%d\n", str1en(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", str1en(*arr));
	printf("%d\n", strlen(arr[1]));
	printf("%d\n", str1en(&arr));
	printf("%d\n", str1en(&arr + 1));
	printf("%d\n", str1en(&arr[0] + 1));
    return 0;
}

详解:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = { 'a ', 'b', 'c', 'd', 'e', 'f' };
	printf("%d\n", str1en(arr));        //随机值,有起始地址arr,但无结束标志'\0'
	printf("%d\n", strlen(arr + 0));    //随机值,arr==arr+0
	printf("%d\n", str1en(*arr));       //error,无起始地址,*arr表示首元素字符'a',其ASCII码是97
	                                    //strlen会将97当作地址来处理,此时会造成越界访问,运行时会报错
	printf("%d\n", strlen(arr[1]));     //error,arr[1]==*(arr+1),原理同上
	printf("%d\n", str1en(&arr));       //随机值,&arr--数组地址。有起始地址,无结束标志
	printf("%d\n", str1en(&arr + 1));   //随机值,跳过一个数组后的地址。有起始地址,无结束标志
	printf("%d\n", str1en(&arr[0] + 1));//随机值,数组第二个元素的地址。有起始地址,无结束标志
	return 0;
}

4. 字符串数组中的sizeof计算

#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	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));

	return 0;
}

详解;

#include<stdio.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", sizeof(arr));        //7,arr单独放,求整个数组的大小。字符串末尾自带'\0',也算一个字节。
	printf("%d\n", sizeof(arr + 0));    //4/8,arr没单独放,表数组首元素地址
	printf("%d\n", sizeof(*arr));       //1,数组首元素的值'a'
	printf("%d\n", sizeof(arr[1]));     //1,数组第二个元素的值'b'
	printf("%d \n", sizeof(&arr));      //4/8,数组地址
	printf("%d\n", sizeof(&arr + 1));   //4/8,跳过一个数组地址后的地址
	printf("%d\n", sizeof(&arr[0] + 1));//4/8,数组第二个元素的地址
	return 0;
}

5. 字符串数组中的strlen计算

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	printf("%d\n", strlen(arr + 0));
	printf("%d\n", strlen(*arr));
	printf("%d\n", str1en(arr[1]));
	printf("%d\n", strlen(&arr));
	printf("%d\n", strlen(&arr + 1));
	printf("%d\n", strlen(&arr[0] + 1));
	return 0;
}

详解:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "abcdef";              //字符串末尾自带结束标志'\0'
	printf("%d\n", strlen(arr));        //6,arr数组首元素地址。有起始地址,有结束标志
	printf("%d\n", strlen(arr + 0));    //6,arr==arr+0
	printf("%d\n", strlen(*arr));       //error,数组首元素的值,无起始地址
	printf("%d\n", str1en(arr[1]));     //error,数组第二个元素的值,无起始地址
	printf("%d\n", strlen(&arr));       //6,&arr--数组地址。数值上等同于arr,有起始地址
	printf("%d\n", strlen(&arr + 1));   //随机值,跳过整个数组后的地址
	printf("%d\n", strlen(&arr[0] + 1));//5,数组第二个元素的地址,有起始地址
	return 0;
}

6. 字符串指针中的sizeof计算

#include<stdio.h>
int main()
{
	char* p = "abcdef";
	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));
	return 0;
}

详解:

#include<stdio.h>
int main()
{
	char* p = "abcdef";
	printf("%d\n", sizeof(p));        //4/8,是一个指针,指向'a'的地址。指针的大小是4或者8
	printf("%d\n", sizeof(p + 1));    //4/8,指针+1,往后走一个char字节。还是指针,指向'b'的地址
	printf("%d\n", sizeof(*p));       //1,表示'a'
	printf("%d\n", sizeof(p[0]));     //1,表示字符'b'
	printf("%d\n", sizeof(&p));       //4/8,&p表示存放指针p的地址,存放地址的又是个指针
	printf("%d\n", sizeof(&p + 1));   //4/8,&p+1表示取出p后面的地址,同样是个指针
	printf("%d\n", sizeof(&p[0] + 1));//4/8,指针指向'b'的地址
	return 0;
}

由于数组名的特性,起始这里的p等同于arr
#include<stdio.h>
int main()
{
    char arr[3] = "abc";
    int* p = arr;
    return 0;
}

 

sizeof与strlen总结:

 sizeof
  sizeof的定义:计算一个变量类型的所占内存大小
 注意:sizeof返回该类型使用的内存量,但值得指出的是,这不必等于其成员的总和
 举例:sizeof(&arr)中,&arr整个数组地址,计算的并不是数组每个元素所占内存的总和,而是&arr指针类型所占的内存量
  sizeof的使用:
 首先关注数组名是否单独 -> 不是单独,关注是否特殊有无& -> 其他判断是地址还是量(变量or变量的赋值)

 


  关于字符串数组
 如果求的是字符数组,和整型数组无区别;求字符串数组,注意末尾的0也算一个字节

 strlen
  strlen的定义:计算字符串的长度
  strlen的使用
 需要开始信号--地址,结束标志--'\0'。开始信号为非地址报错,无结束标志结果为随机值
  关于字符数组
(本来strlen的功能只能求字符串,你非要求字符数组)
 开始信号如果不是地址,即便开始也会报错。结束地址没有0,所求值就是随机值。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值