一、对于sizeof的理解
1. sizeof对常见数据类型的计算
我们首先要明确的是sizeof是一个运算符,并不是函数,它是用来计算所占内存空间的大小,单位是字节,主要是针对我们所给的数据类型分析得出的。
比如:我们用一段不完整的代码表示出来
int a = 2;
char b = '3';
short c = 2;
long long d = 2;
通过sizeof计算得到:
a 的大小是 4,因为 a 的数据类型是 int,int 是4个字节;
b 的大小是 1,因为 b 的数据类型是 char,char 是1个字节;
c 的大小是 2,因为 c 的数据类型是 short,short 是2个字节;
d 的大小是 8,因为 d 的数据类型是 longlong,longlong 是8个字节
所以我们不难看出的是:
sizeof计算所占内存的大小,就是看我们传入的数据,它的数据类型是几个字节,sizeof算出来的就是几个字节。
2. 常见数据类型所占字节大小
1字节 = 8比特位
1比特位 = 1个二进制数
数据类型 | 占内存空间(单位字节) |
int | 4 |
short | 2 |
long | 32位机器为4字节,64位机器为8字节 |
double | 8 |
float | 4 |
指针 | 32位机器为4字节,64位机器为8字节 |
如:int*p,char*ch,short*s,...
这些都是指针类型,所以无论是int*,char*,short*,只要是指针,就是4/8个字节
3. sizeof对数组的计算
3.1 数组名和&数组名
数组名一般表示的是数组首元素的地址,但是有两个例外:
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
3.2 sizeof与数值型数组
我们知道了sizeof是对数据的数据类型的大小的计算,那么对数组是如何计算的呢?
比如:
#include "stdio.h"
int main()
{
int arr[5] = {1,2,3,4,5};
printf("%d\n",sizeof (arr));
printf("%d\n",sizeof (arr[0]));
return 0;
}
我们首先定义了一个一维数值型数组,数组arr有五个元素,我们这里 sizeof(arr),计算的是整个数组的大小,该数组元素有5个,都是int类型,整个数组大小就是 5 * 4 = 20,也就是20个字节。
而 sizeof(arr[0]) 计算的是我们arr数组的第一个元素,下标是0,arr[0] 的数据类型是 int,所以是4个字节。
那么对于其他种类的数值型数组,大家可以自己动手来观察一下。(记住sizeof是根据你给的数据的数据类型来计算的哦)
3.3 sizeof与字符数组
我们上面学会了对数值型的数组进行sizeof计算,那字符数组是否也一样呢?字符串类型呢?
#include "stdio.h"
int main()
{
char arr[5] = {'a','b','c','d','e'};
printf("%d\n",sizeof (arr));
printf("%d\n",sizeof (arr[0]));
return 0;
}
我们看到 sizeof(arr) 得到的是 5,因为这里的 arr 数组名是代表的整个数组,数组一共有五个元素,每个元素是 char类型,所以整个数组大小是5*1 = 5个字节,那么sizeof(arr[0])里面的 arr[0] 数据类型是 char,char是 1 个字节,所以 sizeof 得到就是1个字节。
这跟上面数值型数据是一样的道理,都是看sizeof里面的数据类型是什么。
3.3 sizeof与字符串
#include "stdio.h"
int main()
{
char arr[] = "abcde";
printf("%d\n",sizeof (arr));
printf("%d\n",sizeof (arr[0]));
return 0;
}
在这里我们看到了不一样的结果了,跟以往不同,我们明明是给了字符串 5 个元素,那为什么sizeof(arr) 却得到了 6 呢?
这是因为我们在给字符串赋值的时候,字符串末尾自动补上了一个 ‘\0’
所以 sizeof 在计算大小的时候也会将 ‘\0’ 计算在里面,也就是说,在 sizeof(arr) 里认为,有6个元素,分别是 abcde\0,每个元素都是char类型,就是6个字节。
大家学到了这里其实已经可以自己去推理更多数据类型的计算了,如union联合体类型,结构体类型,这里就涉及到内存对齐的规则了。
4. sizeof的深入
我们在上面讲到,sizeof 计算得到的大小是括号内数据的数据类型所占的字节数
那么sizeof是否可以对算法来计算大小呢?在sizeof里的算式是否真的进行计算了?
我们在下面举例说明:
#include "stdio.h"
int main()
{
int a = 2;
int b = 3;
short c = 1;
printf("%d\n",sizeof (c = a + b));
printf("c=%d\n",c);
}
在上面代码中我们可以看到,sizeof 算出来的是 2,c 的值是1;
那也就是说,sizeof 收到的数据类型是 short,c的值并没有改变,也就是sizeof里面并没有进行计算,但是进行了数据类型的统一。
所以我们在使用sizeof时,只需要关注括号里的数据类型最后是什么,括号里的任何计算都没有进行。
二、strlen函数的定义与用法:
1. strlen函数的定义
首先 strlen 是一个库函数,用来计算字符串长度的,遇到字符串中的‘\0’终止,得到的长度是'\0'之前的字符个数,不包括'\0'本身。
在引用 strlen 函数需要写 #include <string.h> 这个头文件。
2. strlen函数定义类型
size_t strlen (const char * str)
我们可以看到 strlen 的参数是一个指针(地址),返回类型是size_t
size_t 类型也是 unsigned int ,是由 typedef unsigned int size_t 得到的
所以我们可以用 size_t 类型 来接收strlen函数的返回值 ,实参部分要传入一个地址,也就是指针。
3. strlen与字符串
#include "string.h"
#include "stdio.h"
int main()
{
char ch[] = "abcde";
unsigned int n = strlen(ch);
size_t m = strlen(ch);
printf("长度是%d\n",n);
printf("长度是%d\n",m);
return 0;
}
如图可以看出,我们给strlen函数传的形参是ch,也就是数组名,代表首元素地址,所以strlen函数在接收这个首元素地址之后,会往后走下去,直到找到'\0'才停止,返回'\0'之前的字符个数。
也可以看出size_t和unsigned int是一个类型,只不过是通过typedef重命名来的。
4. strlen与字符数组
#include <stdio.h>
#include <string.h>
int main()
{
char ch[5] = {'a', 'b', 'c', 'd', 'e'};
printf("%zu\n", strlen(ch));
return 0;
}
此时的结果是一样的,这是为什么呢?因为strlen是要遇到\0才结束的,字符串的末尾是有隐藏的\0的,但是字符数组的\0是随机的,可能出现在任何位置,所以结果也就是不唯一的;
5.sizeof和strlen的区别
- strlen是一个库函数使用时需要引用#include<string.h>这个头文件,而sizeof是一个运算符号;
- strlen计算的是’\0'之前的字符个数,sizeof计算的是所占空间内存的大小,单位是字节;
- strlen计算时不包含'\0',而sizeof包含'\0';
- strlen遇到'\0'才结束;
- strlen只能用 char* 或者 const char* 做参数,sizeof可以用类型做参数;
三、sizeof和strlen的面试题
sizeof运算与strlen函数的面试笔试题(排版很舒服)-CSDN博客