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;
更新:经过与朋友讨论,发现是否补齐是依据结构体中最大字节的类型来决定的,平台是MINGW win64,如对于如下结构体:
struct{
long long l1;
char c1;
}x;
上述的x大小为16个字节,c1按照long long的大小去补齐,而不是按照上述所说的有一个统一的内存对齐线。可能这个也会因平台而异吧。
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,并借此明晰内存对齐的更多相关文章
- c/c++中关于sizeof、strlen的使用说明
sizeof: 一般指类型.变量等占用的内存大小(由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小) strlen: c字符串的长度(参数必须是字符型指针 char*,当数组名作 ...
- sizeof、strlen、字符串、数组,整到一块,你还清楚吗?
写在前面 sizeof.strlen.字符串.数组,提到这些概念,相信学过C语言的人都能耳熟能详,也能谈得头头是道,但是,在实际运用中,当这些内容交织在一起时,大家却不一定能搞地清清楚楚,本文的目的正 ...
- sizeof和strlen的区别
一.sizeof sizeof(...)是运算符,而不是一个函数. sizeof操作符的结果类型是size_t,在头文件中typedef为unsigned int,其值在编译时即计算好了, ...
- Sizeof与Strlen的区别与联系
转自:http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof sizeof(...)是运算符,在头文件中typedef为uns ...
- Sizeof与Strlen的区别与联系(转)
Sizeof与Strlen的区别与联系 一.sizeof sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型 ...
- sizeof()和strlen()
sizeof计算的是栈中大小 P { margin-bottom: 0.21cm; direction: ltr; color: rgb(0, 0, 0); text-align: justify } ...
- sizeof 和 strlen 的区别
sizeof 和 strlen 都是c/c++ 中常见的符号,他们的功能是判断数组长度.那么他么到底有什么区别 1.sizeof 不是函数,而是一个操作符.字节数的计算在程序编译时进行,而不是在 ...
- C++-sizeof和strlen的区别
一.sizeof sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等. 它的功能是:获得保 ...
- sizeof 和 strlen 区别
Sizeof与Strlen的区别与联系 一.sizeof sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型. ...
- sizeof()与strlen()的区别
首先需要说明的是sizeof和strlen都可以求长度,但是却有很大的区别,简单来说可以概括为以下几点: 1.sizeof是一个关键字,而strlen确实一个函数. 2.sizeof求的是字节长度,而 ...
随机推荐
- js数组常用的方法
var arr=['hello','前端','world']; 1. arr.join(分隔符):将数组中的值拼接成一个字符串,返回这个字符串,默认分隔符"," arr.join( ...
- 设计模式 - 单例模式 Singleton Pattern - C#
单例模式 Singleton Pattern 1.单例模式设计模式属于创建型模式 2.是单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访 ...
- Error java 错误 不支持发行版本5 ( 完美解决版)
问题 在Intellij idea中新建了一个Maven项目,运行时报错如下:Error : java 不支持发行版本5 解决方案 1. 原因 是因为ideal中默认配置中有几个地方的jdk版本与实际 ...
- C# 图片 等 文件 读取操作 的一点提示
源于:在读取图片时,总喜欢首先采用:Image img=Image.FromFile("");操作,这种方式由于 调用图片的程序与图片文件是通过 绝对地址关联的,会造成 当前进程或 ...
- Docker+jenkins 运行 python 自动化
一.实现思路 在 Linux 服务器安装 docker 创建 jenkins 容器 根据自动化项目依赖包构建 python 镜像(构建自动化 python 环境) 运行新的 python 容器,执行 ...
- revit转tileset 3dmax转tileset cesium展示
使用revit软件导出fbx模型: 使用glTFExport导出gltf模型,导出的gltf模型具有属性.但是此处导出gltf模型,不是为了在cesium中加载该gltf模型,主要目的是获取组件属性信 ...
- MATLAB默认路径修改
笔者曾尝试在软件界面的"设置路径"或者Parallel中修改默认路径,但多次尝试均失败.后来经人提点,MATLAB默认文件夹路径可以在桌面图标属性中"起始位置" ...
- El_获取域中存储的值和El_获取域中存储的值_对象值
2获取值 1.el表达式只能从域对象中获取值 2语法: 1.$[域名称.键}:从指定域中获取指定键的值域名称:1.pageScope2.requestScope 3.sessionScope 4.ap ...
- 使用ASP.NET Core开发信息采集系统将用户数据添加至企业微信
一.启动Visual Studio 2019,创建ASP.NET Core Web应用程序 二.在Models文件夹添加新项 Person.cs using System.ComponentModel ...
- 笔精墨妙,妙手丹青,微软开源可视化版本的ChatGPT:Visual ChatGPT,人工智能AI聊天发图片,Python3.10实现
说时迟那时快,微软第一时间发布开源库Visual ChatGPT,把 ChatGPT 的人工智能AI能力和Stable Diffusion以及ControlNet进行了整合.常常被互联网人挂在嘴边的& ...

