sizeof和strlen的对⽐及例题

简介: sizeof和strlen的对⽐及例题
sizeof

在学习操作符的时候,我们学习了 sizeof , sizeof 计算变量所占内存内存空间⼤⼩的,单位是字节,如果操作数是类型的话,计算的是使⽤类型创建的变量所占内存空间的⼤⼩

例如:

int main()
{
  int ret1 = sizeof(int);
  int a = 0;
  int ret2 = sizeof(ret2);
  printf("ret1 = %d\n", ret1);
  printf("ret2 = %d\n", ret2);
  return 0;
}

代码跑起来ret1和ret2输出的值都等于4

同时,sizeof 只关注占⽤内存空间⼤⼩,不在乎内存中存放什么数据

例如:

下列代码输出的三个值都等于4

int main()
{
 int a = 10;
 printf("%d\n", sizeof(a));
 printf("%d\n", sizeof a);
 printf("%d\n", sizeof(int));
 return 0;
}
strlen

strlen 是C语⾔库函数,功能是求字符串⻓度,函数原型如下:

strlen函数不许要改变字符串,所以可以加上const

size_t strlen ( const char * str )

strlen返回的是从str字符串的其实位置开始向后,“\0”前的字符个数

strlen 函数会⼀直向后找 \0 字符,直到找到为⽌,所以可能存在越界查找

例如:

char arr[] = "hello world";
  int ret = strlen(arr);
  printf("%d\n", ret);

ret的值等于多少呢,大家可以思考一下

思考完了吧!

大家要注意,空格也是字符,所以ret等于11!

下面还有一个代码:

char arr[] = "a,b,c,d";
  int ret = strlen(arr);
  printf("%d\n", ret);
  return 0;

可能大部分同学第一眼会觉得ret的值是4

但是结果如下:

因为这个arr存储的单个的字符,并不是字符串,arr中并没有“\0”,所以只能输出随机值

sizeof和strlen的区别

首先看一段代码:

思考一下代码运行结果

#include <stdio.h>
int main()
{
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));
 printf("%d\n", strlen(arr2));
 printf("%d\n", sizeof(arr1));
 printf("%d\n", sizeof(arr1));
 return 0;
}

代码结果输出如下

为什么呢,大家可能对于sizeof(arr2)的值会有疑惑

详解如下

#include <stdio.h>
int main()
{
 char arr1[3] = {'a', 'b', 'c'};
 char arr2[] = "abc";
 printf("%d\n", strlen(arr1));//arr1没有\0,输出随机值
 printf("%d\n", strlen(arr2));//字符串结尾有\0,输出3
 printf("%d\n", sizeof(arr1));//三个字符占三个字节的大小,输出3
 printf("%d\n", sizeof(arr1));//字符串结尾的\0也是一个字符,占一个字节的大小,输出4
 return 0;
}

下面我们对于二者做一个对比:

sizeof

1. sizeof是操作符
2. sizeof计算操作数所占内存的⼤⼩,单位是字节
3. 不关注内存中存放什么数据

strlen

1. strlen是库函数,使⽤需要包含头⽂件 string.h
2. srtlen是求字符串⻓度的,统计的是 \0 之前字符的隔个数
3. 关注内存中是否有 \0 ,如果没有 \0 ,就会持续往后找,可能越界
例题分析
int a[] = { 1,2,3,4 };
  printf("%d\n", sizeof(a));//四个整形数据,大小为16字节
  printf("%d\n", sizeof(a + 0));
  //数组名等于数组首地址,+0后也是一个地址,地址就是指针,指针的大小为4/8个字节在x86/x64环境下
  printf("%d\n", sizeof(*a));//对数组的首地址解引用就是数组首元素,大小为4个字节
  printf("%d\n", sizeof(a + 1));
  //数组名等于数组首地址,+1后也是一个地址,地址就是指针,指针的大小为4/8在x86/x64环境下
  printf("%d\n", sizeof(a[1]));//arr[1]就是首元素,大小为4个字节
  printf("%d\n", sizeof(&a));
  //&数组名是取整个数组的地址,但是指针的大小就是4或8各个字节的大小
  printf("%d\n", sizeof(*&a));//取地址整个数组后解引用就是整个数组的内容,大小为16字节
  printf("%d\n", sizeof(&a + 1));//取地址+1仍然是地址,大小为4/8字节
  printf("%d\n", sizeof(&a[0]));//同上
  printf("%d\n", sizeof(&a[0] + 1));//同上

大家要记住,其实地址就是指针,而指针的大小只能为4或者8个字节

char arr[] = {'a','b','c','d','e'};
printf("%d\n", sizeof(arr));//5个字符的大小为五个字节
printf("%d\n", sizeof(arr+0));//地址的大小为4/8个字节
printf("%d\n", sizeof(*arr));//arr是首元素的地址,解引用就是首元素,大小为1字节
printf("%d\n", sizeof(arr[1]));//首元素大小,1字节
printf("%d\n", sizeof(&arr));//地址的大小为4/8个字节
printf("%d\n", sizeof(&arr+1));//同上
printf("%d\n", sizeof(&arr[0]+1));//同上

下面在同样的数组内容下,我们用strlen来测试

char arr[] = { 'a','b','c','d','e' };
  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));

大家跑起来就会发现

在printf(“%d\n”, strlen(arr));printf(“%d\n”, strlen(arr[1]));
这两行发生了中断,但是将其注释后可以跑动起来,这是为何呢?
大家可以发现,这两行
arr和arr[1]都是字符元素,但是我们知道strlen函数所处理的必须为字符型指针,所以出现中断

其他行都是由于arr中没有“\0”,所以其他行都是输出随机值

通过上面的代码,我们可以总结出一个规律:

1.sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表⽰⾸元素的地址

此外,大家要注意:

再数组中:

&(数组名)+1是跳过整个数组
&(数组名+1)是跳过第一个元素

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//字符串结尾有\0,一共7字节
printf("%d\n", sizeof(arr+0));//指针大小4/8字节
printf("%d\n", sizeof(*arr));//首元素字符a,大小1字节
printf("%d\n", sizeof(arr[1]));//同上
printf("%d\n", sizeof(&arr));//指针大小4/8字节
printf("%d\n", sizeof(&arr+1));//同上
printf("%d\n", sizeof(&arr[0]+1));//同上

char arr[] = "abcdef";
  printf("%d\n", strlen(arr));//六个字符,输出6
  printf("%d\n", strlen(arr + 0));//同上,arr+0依然是arr
  printf("%d\n", strlen(*arr));
  printf("%d\n", strlen(arr[1]));
  printf("%d\n", strlen(&arr));//六个字符,输出6
  printf("%d\n", strlen(&arr + 1));//跳过整个数组,随机值
  printf("%d\n", strlen(&arr[0] + 1));
  //跳过第一个字符a后,从第二个字符b开始遍历,五个字符,输出5

第三行和第四行出现了同样的问题,注释掉输出结果

char* p = "abcdef";
  printf("%d\n", sizeof(p));//p是字符a的地址,指针大小为4/8
  printf("%d\n", sizeof(p + 1));//地址+1仍然为指针,大小为4/8
  printf("%d\n", sizeof(*p));//对a的地址进行解引用,就是a的大小,1字节
  printf("%d\n", sizeof(p[0]));//p[0]就是a,大小为1字节
  printf("%d\n", sizeof(&p));//&数组名,依然是指针,大小为4/8
  printf("%d\n", sizeof(&p + 1));//同上
  printf("%d\n", sizeof(&p[0] + 1));//同上

注意:char* p = "abcdef"是将abcdef中a的地址存入p中,也就是首地址

char* p = "abcdef";
  printf("%d\n", strlen(p));//p是首地址,六个元素,大小6个字节
  printf("%d\n", strlen(p + 1));//p+1开始遍历,五个元素,大小5个字节
  printf("%d\n", strlen(*p));
  printf("%d\n", strlen(p[0]));
  printf("%d\n", strlen(&p));//六个元素,大小6个字节
  printf("%d\n", strlen(&p + 1));//&p是取p的地址,而p又是a的地址,p的地址是未知的,随机值
  printf("%d\n", strlen(&p[0] + 1));//从第二个字符开始遍历,五个元素,大小5个字节

上述代码的三四行代码依旧是老问题,strlen里面只能为指针

int a[3][4] = { 0 };
  printf("%d\n", sizeof(a));//size(a)是取整个二维数组,12个int类型,48个字节
  printf("%d\n", sizeof(a[0][0]));//代表首元素的地址,4个字节
  printf("%d\n", sizeof(a[0]));//a[0]指向的第一行的所有元素,4个元素,14个字节
  printf("%d\n", sizeof(a[0] + 1));//指针大小为4/8字节
  printf("%d\n", sizeof(*(a[0] + 1)));//对a[0]+1再解引用,即第一行第二个元素的大小,4个字节
  printf("%d\n", sizeof(a + 1));//地址+1依然为地址,大小为4/8个字节
  printf("%d\n", sizeof(*(a + 1)));//首地址+1后再解引用,第二行所有元素,16个字节
  printf("%d\n", sizeof(&a[0] + 1));//地址+1依然为地址,大小为4/8个字节
  printf("%d\n", sizeof(*(&a[0] + 1)));//第一行第一个元素+1后解引用,代表第二行所有元素,16个字节
  printf("%d\n", sizeof(*a));//,对a[0][0]解引用,第一行所有元素,16个字节
  printf("%d\n", sizeof(a[3]));//虽然第三行不存在,但是我们依然知道一行有四个int类型的空间,16字节

二维数组中,&a[0]+1后为第二行的首元素,即a[1][0]

相关文章
|
6月前
|
C语言
sizeof与strlen的使用及其区别
sizeof与strlen的使用及其区别
sizeof与strlen的使用及其区别
|
2月前
|
编译器 C++
sizeof 和 strlen 的区别
`sizeof` 和 `strlen` 是 C 和 C++ 中常用的运算符/函数,功能和用途不同
70 11
|
7月前
|
存储 编译器
strlen()和sizeof()的区别
strlen()和sizeof()的区别
54 0
|
7月前
|
Serverless
sizeof和strlen的区别【详解】
sizeof和strlen的区别【详解】
59 0
|
C语言
strlen和sizeof的区别
strlen和sizeof的区别
87 0
strlen与sizeof的区别
strlen与sizeof的区别
84 0
sizeof运算和strlen函数的笔试题(三)
sizeof运算和strlen函数的笔试题(三)
sizeof与strlen区别
sizeof是关键字,参数可以是各种数据(包括函数,类型,对象,数组,指针……)用于计算数据所占字节大小 strlen是函数,参数类型必须是字符型指针(char *),用于计算字符串,从字符串的第一个地址开始遍历,直到遇到‘\0’停止
83 0
|
存储 编译器 C++
sizeof 与strlen的区别与联系
sizeof 与strlen的区别与联系
117 0
sizeof 与strlen的区别与联系