C++ sizeof与strlen,并借此明晰内存对齐
Posted 石中火本火
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ sizeof与strlen,并借此明晰内存对齐相关的知识,希望对你有一定的参考价值。
前言
sizeof()
与strlen()
都是为了获取对象的长度。在正常编写C++的算法程序代码时,可能这两个都很少用到,因为各种stl容器的封装已经给了我们很大的便利,比如我们在想要获取自定义的vector容器里的元素个数,想要获取string类型的字符串的长度时,都只需要调用他们的.size()
方法就可以得到容器的长度或者元素的个数。诚然如此,仍会有很多情况需要获取未定义大小方法的对象的大小,比如一个结构体,所以我们还是需要关注这些偏底层的知识,下面就来细细阐述:
sizeof()使用
sizeof() 计算的是变量或类型所占用的内存字节数, 而strlen计算的只能是变量的长度;
#include<iostream>
using namespace std;
struct Node
int val1; // 4 bytes
int val2; // 4 bytes
Node* left; // 8bytes
Node* right; // 8 bytes
;
int main()
cout<<"int:"<<sizeof(int)<<endl; // 4 bytes
cout<<"char:"<<sizeof(char)<<endl; // 1 bytes
cout<<"int*:"<<sizeof(int*)<<endl; // 8 bytes
cout<<"char*:"<<sizeof(char*)<<endl; // 8 bytes
cout<<"Node*:"<<sizeof(Node*)<<endl; // 8 bytes
int x;
cout<<"int x:"<<sizeof(x)<<endl; // 4 bytes
char s[] = "123 456";
cout<<"s[]:"<<sizeof(s)<<endl; // 8 bytes, including \'\\0\'
Node* node = new Node();
cout<<"node:"<<sizeof(*node)<<endl; // 24 bytes, or 8 bytes if sizeof(node), because node is just a pointer.
return 0;
总结:
sizeof对于所有的指针,无论指针类型是什么,其所计算的都是指针本身也就是存储的地址值的长度,而对于64位机器,8 bytes足以访问其所有的内存地址(32位机器是4 bytes)。
而对于字符数组类型,会自动计算在其末尾的\'\\0\'运算符,是比strlen()多一个单位的。
对于一个自定义结构体,会自动计算所有成员变量的和。从上可以看出对于两个int类型,两个指针类型他们的字节数分别是4, 4, 8, 8,于是总大小为24bytes。但此时有一个问题,如果把第二个int换为char,答案就是21 bytes了吗?答案是否定的,仍然是24 bytes,这就是内存对齐所导致的结果,sizeof()的值就是对齐之后的值。
关于对齐可以参考:https://zhuanlan.zhihu.com/p/30007037
此处放几个截图可以清晰的说明内存如何对齐(以四字节为对齐标准):
其对齐后的内存布局分别如下:
另外还需注意的是关于最后是否补齐为4或8字节的整数倍还是依具体平台而定。自测如下结构体,只占3字节并未补齐,但是运行x2却发现又补齐了,颇为奇怪:
struct Test
char c1;
char c2;
char c3;
test;
strlen()使用
strlen()是函数,只能去计算以空字符\'\\0\'结尾的字符串,否则是未定义的行为,所以他无法去计算结构体的大小。定义如下:
size_t strlen ( const char * str );
(参数中只能传递字符串类型)
具体使用:
char s[] = "Hello, world!";
strlen(s) // 输出 13,即字符串 s 中有 13 个字符(不包括结尾的空字符 \'\\0\')
区别
那么除了上述用法和结果上的一些区别,即sizeof可以用在任意类型与对象,统计全部的字符大小包括\'\\0\', 而strlen只能统计字符串的长度(不统计\'\\0\').在底层实现时也有一些区别:
sizeof()是运算符,strlen()是库函数
sizeof()在编译时计算好了,strlen()在运行时计算
sizeof()计算出对象使用的最大字节数,strlen()计算字符串的实际长度
sizeof()的参数类型多样化(数组,指针,对象,函数都可以),strlen()的参数必须是字符型指针(传入数组时自动退化为指针)
其实两者之前共同点就只在于都可以计算字符数组的长度,其他尽不相同。
以上是关于C++ sizeof与strlen,并借此明晰内存对齐的主要内容,如果未能解决你的问题,请参考以下文章