前言

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,并借此明晰内存对齐的更多相关文章

  1. c/c++中关于sizeof、strlen的使用说明

    sizeof: 一般指类型.变量等占用的内存大小(由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小) strlen: c字符串的长度(参数必须是字符型指针 char*,当数组名作 ...

  2. sizeof、strlen、字符串、数组,整到一块,你还清楚吗?

    写在前面 sizeof.strlen.字符串.数组,提到这些概念,相信学过C语言的人都能耳熟能详,也能谈得头头是道,但是,在实际运用中,当这些内容交织在一起时,大家却不一定能搞地清清楚楚,本文的目的正 ...

  3. sizeof和strlen的区别

    一.sizeof    sizeof(...)是运算符,而不是一个函数.    sizeof操作符的结果类型是size_t,在头文件中typedef为unsigned int,其值在编译时即计算好了, ...

  4. Sizeof与Strlen的区别与联系

    转自:http://www.cnblogs.com/carekee/articles/1630789.html 一.sizeof    sizeof(...)是运算符,在头文件中typedef为uns ...

  5. Sizeof与Strlen的区别与联系(转)

    Sizeof与Strlen的区别与联系 一.sizeof     sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型 ...

  6. sizeof()和strlen()

    sizeof计算的是栈中大小 P { margin-bottom: 0.21cm; direction: ltr; color: rgb(0, 0, 0); text-align: justify } ...

  7. sizeof 和 strlen 的区别

    sizeof 和 strlen 都是c/c++ 中常见的符号,他们的功能是判断数组长度.那么他么到底有什么区别 1.sizeof    不是函数,而是一个操作符.字节数的计算在程序编译时进行,而不是在 ...

  8. C++-sizeof和strlen的区别

    一.sizeof    sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型.对象.函数等.    它的功能是:获得保 ...

  9. sizeof 和 strlen 区别

    Sizeof与Strlen的区别与联系 一.sizeof    sizeof(...)是运算符,在头文件中typedef为unsigned int,其值在编译时即计算好了,参数可以是数组.指针.类型. ...

  10. sizeof()与strlen()的区别

    首先需要说明的是sizeof和strlen都可以求长度,但是却有很大的区别,简单来说可以概括为以下几点: 1.sizeof是一个关键字,而strlen确实一个函数. 2.sizeof求的是字节长度,而 ...

随机推荐

  1. js数组常用的方法

    var arr=['hello','前端','world']; 1. arr.join(分隔符):将数组中的值拼接成一个字符串,返回这个字符串,默认分隔符"," arr.join( ...

  2. 设计模式 - 单例模式 Singleton Pattern - C#

    单例模式 Singleton Pattern 1.单例模式设计模式属于创建型模式 2.是单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建.这个类提供了一种访问其唯一的对象的方式,可以直接访 ...

  3. Error java 错误 不支持发行版本5 ( 完美解决版)

    问题 在Intellij idea中新建了一个Maven项目,运行时报错如下:Error : java 不支持发行版本5 解决方案 1. 原因 是因为ideal中默认配置中有几个地方的jdk版本与实际 ...

  4. C# 图片 等 文件 读取操作 的一点提示

    源于:在读取图片时,总喜欢首先采用:Image img=Image.FromFile("");操作,这种方式由于 调用图片的程序与图片文件是通过 绝对地址关联的,会造成 当前进程或 ...

  5. Docker+jenkins 运行 python 自动化

    一.实现思路 在 Linux 服务器安装 docker 创建 jenkins 容器 根据自动化项目依赖包构建 python 镜像(构建自动化 python 环境) 运行新的 python 容器,执行 ...

  6. revit转tileset 3dmax转tileset cesium展示

    使用revit软件导出fbx模型: 使用glTFExport导出gltf模型,导出的gltf模型具有属性.但是此处导出gltf模型,不是为了在cesium中加载该gltf模型,主要目的是获取组件属性信 ...

  7. MATLAB默认路径修改

    笔者曾尝试在软件界面的"设置路径"或者Parallel中修改默认路径,但多次尝试均失败.后来经人提点,MATLAB默认文件夹路径可以在桌面图标属性中"起始位置" ...

  8. El_获取域中存储的值和El_获取域中存储的值_对象值

    2获取值 1.el表达式只能从域对象中获取值 2语法: 1.$[域名称.键}:从指定域中获取指定键的值域名称:1.pageScope2.requestScope 3.sessionScope 4.ap ...

  9. 使用ASP.NET Core开发信息采集系统将用户数据添加至企业微信

    一.启动Visual Studio 2019,创建ASP.NET Core Web应用程序 二.在Models文件夹添加新项 Person.cs using System.ComponentModel ...

  10. 笔精墨妙,妙手丹青,微软开源可视化版本的ChatGPT:Visual ChatGPT,人工智能AI聊天发图片,Python3.10实现

    说时迟那时快,微软第一时间发布开源库Visual ChatGPT,把 ChatGPT 的人工智能AI能力和Stable Diffusion以及ControlNet进行了整合.常常被互联网人挂在嘴边的& ...