C++八股:sizeof 和 strlen
C/C++ 中 sizeof 关键字 | 编程指北-计算机学习指南
大部分内容都来自上面这个指南,这里只是自己总结一下。
strlen 是头文件 cstring 中的函数,而 sizeof 是 C++ 中的运算符。
1.strlen
strlen 是一个 C 标准库中的函数,用于计算 C 风格字符串(以空字符 '\0' 结尾的字符数组)的长度,即不包括结尾的空字符的字符个数。不能计算string类型数据的长度。
strlen的码源如下:
size_t strlen(const char *str) {
size_t length = 0;
while (*str++)
++length;
return length;
}
2.sizeof
几个关键的点:
-
指针的大小永远是固定的,取决于处理器位数,32位就是 4 字节,64位就是 8 字节
-
数组作为函数参数时会退化为指针,大小要按指针的计算, 详细请看这篇文章数组退化为指针
-
struct 结构体要考虑字节对齐,字节对齐的具体规则请看这篇文章: 字节对齐
-
字符串数组要算上末尾的 '\0'
举例:
// 前提: 64 位电脑上
char str[] = "Hello World" ;
char *p = str;
double *dp;
int n = 10;
sizeof(str )=___12_____ // 11个字符 + 末尾'\0',总结第四点
sizeof ( p ) = ___8 ___ // 64 位电脑,指针 8 个字节
sizeof ( n ) = ___4______ // int 一般 4 个字节
void Func (char str[10])
{
sizeof( str ) = _8__ // 数组做参数退化为 char类型指针,即 8 个字节,总结第2点
}
void *vp = malloc( 100 );
sizeof ( vp )=__8____ // vp 是一个 void 类型指针,还是 8 个字节
struct AlignedStruct {
char a; // 本来1字节,padding 3 字节
int b; // 4 字节
short c; // 本来 short 2字节,但是整体需要按照 4 字节对齐(成员对齐边界最大的是int 4) ,
//所以需要padding 2,总共: 4 + 4 + 4
};
struct B{
double b; //8字节
int a; //4字节
char c; //1字节,和前面的4字节一起合并到一个8字节里面
};
指针,引用,sizeof
#include<bits/stdc++.h>
using namespace std;
void print1(int v[10]){
cout<<sizeof(v)<<endl; //8,指针的大小
}
void print2(int (&v)[10]){
cout<<sizeof(v)<<endl; //40,arr数组的大小
}
void print3(int* v){
cout<<sizeof(*v)<<endl; //4,arr[0]这个int的大小
}
int main(){
int arr[10]={0};
print1(arr);
print2(arr);
print3(arr);
return 0;
}
一看没什么问题,但是要知道引用底层使用指针来实现的,那为什么同样是指针引用算出来了整个数组的大小,而指针只算出来了一个Int的大小。
我认为原因如下:
程序执行分为这5步:
- 预处理 (Preprocessing)
- 编译 (Compilation)
- 汇编 (Assembly)
- 链接 (Linking)
- 加载 (Loading) 与 运行 (Execution)
sizeof是运算符,它会在预处理阶段就变为一个具体的数值,而把引用具体实现为指针是在汇编阶段。所以在算sizeof的时候引用还没有变为指针,它的处理逻辑应该是引用单独的一套。
问了gemini具体执行应该是这样的:
1.sizeof进行替换,比如print1中的sizeof(v)会被替换为sizeof(int *)。就是说他会根据变量名查找具体的类型,然后把sizeof的参数变为具体的类型。
void print1(int v[10]){
cout<<sizeof(v)<<endl; //替换为sizeof(int *);
}
2.知道了他会替换,我们来看print2中的执行
void print2(int (&v)[10]){
// 1. v 的类型是 int (&)[10](对10个int的数组的引用),也就是说v还是一个引用
// 2. C++ 标准规定:sizeof(引用) == sizeof(被引用的类型)
// 3. v 引用的类型是 int [10]
// 4. 因此,sizeof(v) 等价于 sizeof(int [10])
cout<<sizeof(v)<<endl; // 40
}
所以虽然引用底层使用指针实现的,但是sizeof是在预处理期就运行的,还不涉及底层,这时候引用可以得到arr数组实际的大小是通过c++标准规定实现的。
更多推荐


所有评论(0)