前言

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. 2vue

    事件 v-on:click="handle" @click="handle" handle创建在methods里 <!DOCTYPE html> & ...

  2. mysql 设置相关

    告诉mysql客户端这边的文字编码 告诉mysql希望返回的结果集编码: set character_set_client=gbk; set character_set_results=gbk;   ...

  3. Websocket是什么?

    一. WebSocket是什么? Websocket是一种网络通信协议,是一个在计算机里专门在[两点]之间传输数据的约定和规范. 二. 为什么存在WebSocket? 因为 HTTP 协议有一个缺陷: ...

  4. 几个Python线程坑,和连接池的坑

    urlretrieve 没有超时,需要通过socket来设置 socket.setdefaulttimeout(10) 而且还需要为他设置连接池,所以直接改用requests来下载文件 def dow ...

  5. Hyperkernel验证实验的复现与z3环境初识

    Hyperkernel验证实验的复现与z3环境初识 前言 建议顺序阅读本文!禁止转载.--@CarpVexing(https://www.cnblogs.com/CarpVexing/p/159483 ...

  6. JSP环境搭建及入门 和 虚拟路径和虚拟主机

    Jsp:是一个动态网页,而不是静态网页 html,css,js,Jquery:是静态网页 动态网页是随着,时间,地点,用户操作,而改变 静态不需要jsp 动态是需要的 BS 可以通过浏览器直接访问浏览 ...

  7. 使用ansible批量推送公钥

    准备两个yml文件 send-pubkey.yml - hosts: all remote_user: root # 连接远程主机的用户,密码就是文件中设置好的 ansible_ssh_pass 的值 ...

  8. Leecode 160.相交链表(Java 哈希表、双指针 两种方法)

    找两个链表第一次指针相同的地方     想法:(本来是没有的,因为没读懂题目描述= =) 1.两个指针,长的先走(长减短相差的长度)这么多的步数,然后就可以开始比较指针,直到指向为空,期间如果指针相同 ...

  9. Windows11右键改Win10

    Win11改Win10右键模式 1.以管理员身份运行CMD控制台 2.在控制台中输入下列代码后回车执行 reg add "HKCU\Software\Classes\CLSID\{86ca1 ...

  10. [Unity移动端]Mono与IL2Cpp

    参考链接: https://blog.csdn.net/linxinfa/article/details/87358809 https://blog.csdn.net/Aison_/article/d ...