C/C++ sizeof

介绍

sizeof 是一个关键字、操作符,也是一个编译时运算符

作用:返回一个对象或者类型所占的内存字节数

使用方法

sizeof(type_name);//sizeof(类型)
sizeof(object);//sizeof(对象)

注意:

sizeof 操作符不能用于函数类型,不完全类型或位字段

不完全类型:指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void 类型……

sizeof(void) 不是正确形式

基本数据类型

本质:将对象转换成对象类型进行计算,同种类型的不同对象其 sizeof 值相同

常见字长:

#include <iostream>
#include <string>
using namespace std;
int main() {cout << "sizeof(bool)=" << sizeof(bool) << endl;				// 1	cout << "sizeof(char)=" << sizeof(char) << endl;				// 1	cout << "sizeof(short)=" << sizeof(short int) << endl;		    // 2cout << "sizeof(int)=" << sizeof(int) << endl;				    // 4cout << "sizeof(long)=" << sizeof(long int) << endl;			// 4cout << "sizeof(long long)=" << sizeof(long long) << endl;	    // 8cout << "sizeof(float)=" << sizeof(float) << endl;			    // 4cout << "sizeof(double)=" << sizeof(double) << endl;			// 8return 0;
}

表达式

编译器根据表达式的最终结果类型确定大小,sizeof 是编译时进行计算,与运行时无关,不会对表达式进行计算

#include <iostream>
#include <string>
using namespace std;
int main() {int i = 8;cout << "sizeof(i)=" << sizeof(i) << endl;					// 4cout << "sizeof(i=5)=" << sizeof(i = 5) << endl;		    // 4cout << i << endl;//sizeof(i = 5)不会改变i的值cout << "sizeof(i++)=" << sizeof(i++) << endl;		        // 4cout << i << endl;//sizeof(i++)不会改变i的值return 0;
}

指针

指针变量的 sizeof 值与指针所指的对象类型无关,与指针申请的空间大小无关,所有指针变量所占内存大小均相等

32 位系统中,返回 4;64 位系统中,返回 8

#include<iostream>
using namespace std;
char fun() {return 'c';
}
int main() {//指向char类型变量的指针char c;char* ptr_char = &c;cout << "sizeof(ptr_char) = " << sizeof(ptr_char) << endl;         // 8//指向int类型变量的指针int i;int* ptr_int = &i;cout << "sizeof(ptr_int) = " << sizeof(ptr_int) << endl;           // 8//指向double类型变量的指针double* ptr_double = new double[10];cout << "sizeof(ptr_double) = " << sizeof(ptr_double) << endl;     // 8//二级指针char** two_ptr_char = &ptr_char;cout << "sizeof(二级指针) = " << sizeof(two_ptr_char) << endl;      // 8//函数指针:指向函数的指针,指针函数:返回值是指针的函数void (*ptr_f)();cout << "sizeof(函数指针) = " << sizeof(ptr_f) << endl;             // 8//&fun:一个函数指针cout << "sizeof(&fun) = " << sizeof(&fun) << endl;                 // 8//fun():一次函数调用cout << "sizeof(fun()) = " << sizeof(fun()) << endl;// 1,返回返回值的类型的大小//(*fun)():一次函数调用cout << "sizeof((*fun)()) = " << sizeof((*fun)()) << endl;// 1,返回返回值的类型的大小return 0;
}

数组

数组所有元素所占用的大小

#include<iostream>
using namespace std;
void foo(int a[3]) {//当数组作为函数形参时,以指针类型进行传递cout << "sizeof(a) = " << sizeof(a) << endl;   // 8,a以指针传递,故a为指针
}int main() {//二维数组int A[3][5];cout << "sizeof(A) = " << sizeof(A) << endl;                // 60=3*5*4,A的数据类型为int[3][5]cout << "sizeof(A[0]) = " << sizeof(A[0]) << endl;          // 20=5*4,A[0]的数据类型为int[5]cout << "sizeof(A[4]) = " << sizeof(A[4]) << endl;          // 20=5*4,A[4]的数据类型为int[5]//虽然A[4]下标越界,但sizeof只关心数据类型,在编译阶段已经完成,不会造成运行错误cout << "sizeof(A[0][0]) = " << sizeof(A[0][0]) << endl;    // 4=1*4,A[0][0]的数据类型为intcout << "sizeof(A[0][1]) = " << sizeof(A[0][1]) << endl;    // 4=1*4,A[0][1]的数据类型为int//字符串char c[] = "abcdef";cout << "sizeof(c) = " << sizeof(c) << endl;                // 7=6+1('\0')//指针数组=指针内存大小*元素个数char* ch[10];cout << "sizeof(ch) = " << sizeof(ch) << endl;       // 80,ch是一个数组,数组的元素是指针cout << "sizeof(*ch) = " << sizeof(*ch) << endl;     // 8,*ch是一个指针,是数组的第一个元素cout << "sizeof(**ch) = " << sizeof(**ch) << endl;   // 1,**ch是一个char变量,是数组的第一个元素(指针)指向的变量//数组指针int* (*d)[3][6];cout << "sizeof(d) = " << sizeof(d) << endl;         // 8,d是一个指针,指向一个二维数组,二维数组的元素是int类型的指针cout << "sizeof(*d) = " << sizeof(*d) << endl;       // 144=3*6*8,*d是一个二维数组,是d指向的二维数组cout << "sizeof(**d) = " << sizeof(**d) << endl;     // 48=6*8,**d是一个一维数组cout << "sizeof(***d) = " << sizeof(***d) << endl;   // 8,***d是一个指针cout << "sizeof(****d) = " << sizeof(****d) << endl; // 4,****d是一个int变量//一维数组int nums[] = { 1,2,3 };cout << "sizeof(nums) = " << sizeof(nums) << endl;   // 12=3*4foo(nums);//参数以指针传递return 0;
}

字符串

#include <iostream>
#include <string>
#include <cstring>
using namespace std;int main() {const char* strPtr = "hyy";char strs[] = "hyy";string str = "h";cout << "sizeof(strPtr) = " << sizeof(strPtr) << endl;   // 8,strPtr是一个指针cout << "sizeof(strs) = " << sizeof(strs) << endl;       // 4,strs是一个字符数组,包括 '\0'cout << "sizeof(str) = " << sizeof(str) << endl;         // 40,str是一个string类对象,是string类所占的实际内存cout << "sizeof(string) = " << sizeof(string) << endl;   // 40cout << "strlen(strPtr) = " << strlen(strPtr) << endl;   // 3cout << "strlen(strs) = " << strlen(strs) << endl;       // 3cout << "str.size() = " << str.size() << endl;           // 1return 0;
}

函数

返回函数返回值类型的大小,函数并不会被调用执行

sizeof(函数名(实参表))

PS:

  1. 不可以对返回值类型为空的函数求值
  2. 不可以对函数名求值
  3. 对有参数的函数,须写上实参列表
#include <iostream>
using namespace std;int intfun() {return 1;
}double doufun(int a, double b) {return a + b;
}void voidfun() { }int main() {// cout << "sizeof(intfun) = " << sizeof(intfun) << endl;               //编译失败   cout << "sizeof(intfun()) = " << sizeof(intfun()) << endl;              // 4cout << "sizeof(doufun(1, 1.5)) = " << sizeof(doufun(1, 1.5)) << endl;  // 8,不可省略实参列表// cout << "sizeof(voidfun()) = " << sizeof(voidfun()) << endl;         //编译失败return 0;
}

结构体

内存对齐

对其目的:减少访存指令周期,提高 CPU 存储速度

一般情况下,结构体所占内存大小并非元素本身大小之和

#include <iostream>
using namespace std;struct S1 {char c;int i;
};int main() { cout << "sizeof(S1) = " << sizeof(S1) << endl;   // 8return 0;
}// sizeof(S1) =/= sizeof(char) + sizeof(int)

结构体或类成员变量具有不同类型时,需进行成员变量的对齐

每个特定平台上的编译器都有自己的默认“对齐系数”(对齐模数)

32 位机对齐(默认)是按4字节对齐,而 64 位机(默认)是按8字节对齐

模数在不同平台值不同,可使用#pragmapack(n)改变

对其原则:

  1. 结构体内存大小应按最大元素大小对齐,若最大元素大小超过模数,应按模数大小对齐
  2. 若结构体的最大元素大小超过模数,结构体的起始地址是可以被模数整除的;若最大元素大小没有超过模数,那么其起始地址是可以被最大元素大小整除
  3. 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍,若有需要编译器会在成员之间加上填充字节(internal adding),首个成员从偏移量为 0 的位置开始存
  4. 结构体的总大小为结构体最宽基本成员类型大小的整数倍,若有需要编译器会在最末一个成员之后加上填充字节(trailing padding)

空结构体(不含数据成员)的 sizeof 值为 1

静态成员存放在静态存储区,不占用结构体的大小

成员函数不占用结构体的大小

#include <iostream>
using namespace std;struct st0 {char a;     // 1 + pad(7)char* a1;   // 8int c;      // 4 + pad(4)
};              // 24
//a 的长度为 1,所占的地址为 0;
//a1 的长度为 8,偏移前的首地址为 1,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 8 即可,故加上 7 个填充字节;
//c 的长度为 4,首地址为 16,结构体的大小为 20,不是最宽基本成员(8)的整数倍,故需填充 4 个字节,使得结构体总大小为 24struct st1 {char a;     // 1 + pad(7)double b;   // 8int c;      // 4char d;     // 1 + pad(3)
};              // 24
// a 的长度为 1,所占的地址为 0;
// b 的长度为 8,偏移前的首地址为 1,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 8 即可,故加上 7 个填充字节;
// c 的长度为 4,首地址为 16
// d 的长度为 1,首地址为 20,结构体大小为 21,不是最宽基本成员(8)的整数倍,故需填充 3 个字节,使得结构体总大小为 24struct st2 {char a;     // 1char a1;    // 1 + pad(2)int c;      // 4st1 st;     // 24char d;     // 1 + aad(7) 
};              // 40
// a 的长度为 1,所占的地址为 0;
// a1 的长度为 1,所占的地址为 1,首地址是成员大小的整数倍,故不需要偏移
// c 的长度为 4,偏移前的首地址为 2,因为首地址不是成员大小的整数倍,故需偏移,使其首地址为 4 即可,故加上 2 个填充字节;
// st 的长度为 24,首地址为 8,虽然首地址不是成员大小的整数倍,但因为成员大小超过默认模数,故以模数进行对齐
// d 的长度为 1,首地址为 32,结构体大小为 33,不是模数(8)的整数倍(因为最宽基本成员类型大小超过模数,故以模数进行对齐),故需填充 7 个字节,使得结构体总大小为 40int main() { cout << "sizeof(st0) = " << sizeof(st0) << endl;   // 24// 获取成员在结构体的地址偏移量cout << "offsetof(st0, a) = " << offsetof(st0, a) << endl;   // 0cout << "offsetof(st0, a1) = " << offsetof(st0, a1) << endl; // 8cout << "offsetof(st0, c) = " << offsetof(st0, c) << endl;   // 16cout << "sizeof(st1) = " << sizeof(st1) << endl;   // 24cout << "offsetof(st1, a) = " << offsetof(st1, a) << endl;   // 0cout << "offsetof(st1, b) = " << offsetof(st1, b) << endl;   // 8cout << "offsetof(st1, c) = " << offsetof(st1, c) << endl;   // 16cout << "offsetof(st1, d) = " << offsetof(st1, d) << endl;   // 20cout << "sizeof(st2) = " << sizeof(st2) << endl;   // 40cout << "offsetof(st2, a) = " << offsetof(st2, a) << endl;   // 0cout << "offsetof(st2, a1) = " << offsetof(st2, a1) << endl; // 1cout << "offsetof(st2, c) = " << offsetof(st2, c) << endl;   // 4cout << "offsetof(st2, st) = " << offsetof(st2, st) << endl; // 8cout << "offsetof(st2, d) = " << offsetof(st2, d) << endl;   // 32return 0;
}

进行 sizeof 计算时,类与结构体类似

  • 空类大小为 1
  • 类的成员函数不占用结构体大小。类对象的大小由其数据成员决定
  • 类和结构体一样,需要对齐
  • 类若包含虚函数,编译器会在类对象中插入一个指向虚函数表的指针(多个虚函数也只有一个),以帮助实现虚函数的动态调用
  • 静态成员存放在静态存储区,不占用类的大小
#include <iostream>
using namespace std;class c0 {char a;     // 1 + pad(7)char* a1;   // 8int c;      // 4 + pad(4)
};              // 24class c1 {char a;     // 1 + pad(7)double b;   // 8int c;      // 4char d;     // 1 + pad(3)
};              // 24class c2 {char a;     // 1char a1;    // 1 + pad(2)int c;      // 4c1 cla;     // 24char d;     // 1 + pad(7) 
};              // 40struct c3
{static int i;       // 静态成员int fun();          // 成员函数int d;              // 4char ch;            // 1 + pad(3)virtual int vir1(); // 8 (64bit)
};                      // 16class A{};   // 1,空类class B {virtual int fun(){   // 虚函数return 0;}
};                       // 8class C {static int a;   // 静态成员void fun();     // 成员函数
};                  // 1int main() { cout << "sizeof(c0) = " << sizeof(c0) << endl;   // 24cout << "sizeof(c1) = " << sizeof(c1) << endl;   // 24cout << "sizeof(c2) = " << sizeof(c2) << endl;   // 40cout << "sizeof(c3) = " << sizeof(c3) << endl;   // 16cout << "sizeof(A) = " << sizeof(A) << endl;     // 1A a;cout << "sizeof(a) = " << sizeof(a) << endl;     // 1,空类的实例大小就是类的大小cout << "sizeof(B) = " << sizeof(B) << endl;     // 8B b;cout << "sizeof(b) = " << sizeof(b) << endl;     // 8cout << "sizeof(C) = " << sizeof(C) << endl;   // 1C c;cout << "sizeof(c) = " << sizeof(c) << endl;   // 1return 0;
}

string

sizeof(string)计算 string 变量在内存中的空间大小,与字符串长度无关

string 在内存中的布局:

vector

sizeof(vector)计算 vector 变量在内存中的空间大小,与变量中元素的个数无关

联合体

结构体在内存组织上是顺序式的,联合体是重叠式,各成员共享一段内存,所以整个联合体的 sizeof 就是每个成员 sizeof 的最大值

#include <iostream>
using namespace std;class c {char a;     // 1 + pad(7)char* a1;   // 8int c;      // 4 + pad(4)
};              // 24union U {int i;      // 4char c;     // 1class c c_c;// 24
};
int main() { cout << "sizeof(U) = " << sizeof(U) << endl;   // 24return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/177491.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis-Plus返回getOne返回null疑惑

getOne返回null 问题描述分析过程总结 问题描述 在数据库建了一张表主要包括两个字段master_id和slave_id;主要的额外字段max_lots 默认值是null&#xff1b; 当调用getOne进行查询结果是null&#xff0c;但实际情况是数据库时应该返回值的&#xff1b; AotfxMasterSlave ex…

【Unity】Addressables资源管理笔记

【Unity】Addressables资源管理笔记 Addressables是一种用于管理资源的系统。允许以一种灵活的方式加载、卸载和管理资源&#xff0c;无论是场景、预制件、材质、纹理、音频剪辑等。 一、快速实现 安装Addressables插件 把对象添加到组 1&#xff09;打开AddressablesGroups面…

接口测试 —— Jmeter 之测试片段的应用

一、什么是测试片段&#xff1f; 控制器上一种特殊的线程组&#xff0c;它与线程组处于一个层级。与线程组不同的就是&#xff1a;测试片段不会执行。它是一个模块控制器或者被控制器应用时才会被执行。通常与Include Controller或模块控制器一起使用。 1.1 那它有啥作用&…

在excel中如何打出上标、下标

例如&#xff0c;想把A2的2变为下标。 在单元中输入内容&#xff1a; 选中2&#xff1a; 右键单击&#xff0c;然后点击“设置单元格格式”&#xff1a; 在特殊效果的下面勾选“下标”&#xff0c;然后点击下面的“确定”按钮&#xff1a; 就将2变为下标了&#xff1a;…

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models

2021-arxiv-LoRA Low-Rank Adaptation of Large Language Models Paper: https://arxiv.org/abs/2106.09685 Code: https://github.com/microsoft/LoRA 大型语言模型的LoRA低秩自适应 自然语言处理的一个重要范式包括对通用领域数据的大规模预训练和对特定任务或领域的适应。…

数据仓库-拉链表

在数据仓库中制作拉链表&#xff0c;可以按照以下步骤进行&#xff1a; 确定需求&#xff1a;首先明确需要使用拉链表的场景和需求。例如&#xff0c;可能需要记录历史数据的变化&#xff0c;以便进行时间序列分析等。设计表结构&#xff1a;在数据仓库中&#xff0c;拉链表通…

LeetCode----84. 柱状图中最大的矩形

题目 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 1: 输入:heights = [2,1,5,6,2,3] 输出:10 解释:最大的矩形为图中红色区域,面积为 10 示例 2: 输入: heights =…

基于SSM的理发店管理系统

基于SSM的理发店管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 公告信息 管理员界面 用户界面 摘要 基于SSM&#xff08;Spring、Spring MVC、…

基于springboot漫画动漫网站

基于springbootvue漫画动漫网站 摘要 基于Spring Boot的漫画动漫网站是一个精彩的项目&#xff0c;它结合了现代Web开发技术和漫画爱好者的热情。这个网站的目标是为用户提供一个便捷的平台&#xff0c;让他们能够欣赏各种漫画和动漫作品&#xff0c;与其他爱好者分享他们的兴趣…

mfc140u.dll丢失怎么修复,mfc140u.dll文件有什么作用

今天我想和大家分享的是关于mfc140u.dll文件丢失的解决方法。在我们使用电脑的过程中&#xff0c;有时候会遇到一些错误提示&#xff0c;其中比较常见的就是“无法找到mfc140u.dll文件”。那么&#xff0c;这个文件是什么呢&#xff1f;它有什么作用呢&#xff1f; 首先&#…

模型实际训练笔记2-VGG

1、VGG简介&#xff1a; VGG网络是由牛津大学的视觉几何组&#xff08;visual geometry group&#xff09;首次提出来的。 VGG 网络&#xff0c;也称为Visual Geometry Group网络&#xff0c;是计算机视觉领域的一个深度卷积神经网络架构。它于2014年由牛津大学的研究团队开发…

SpringCloud-Alibaba-Nacos2.0.4

SpringCloud-Alibaba-Nacos2.0.4 SpringCloud Alibaba版本选择&#xff08;截止到2023年3月12日&#xff09; Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2021.0.4.0*Spring Cloud 2021.0.42.6.11 SpringCloud Alibaba-2021.0.4.0组件版本关系 S…

Ant Design Vue Table 表格内容高度自适应+固定表头踩坑

前言 对于非专业前端开发者来使用 Ant Design UI 组件来开发企业级后台管理系统来说是非常不错的选择&#xff0c;但这并不意味着我们能够用好这个框架&#xff0c;因为 UI 交互上和有许多细节上的问题对于非专业前端来说并不容易解决&#xff0c;最近在使用 Table 组件时就遇…

多路转接之epoll

本篇博客介绍&#xff1a; 多路转接之epoll 多路转接之epoll 初识epollepoll相关系统调用epoll的工作原理epoll服务器编写成员变量构造函数 循环函数HandlerEvent函数epoll的优缺点 我们学习epoll分为四部分 快速理解部分概念 快速的看一下部分接口讲解epoll的工作原理手写epo…

软件测试之用例篇(万能公式、具体方法)

目录 1. 概念 2. 万能公式 3.具体设计测试用例的方法 &#xff08;1&#xff09;等价类 &#xff08;2&#xff09;边界值 &#xff08;3&#xff09;判定表(因果图) &#xff08;4&#xff09;场景设计法 &#xff08;5&#xff09;正交法 如何使用 allparis 生成正交…

洞见UI自动化测试

随着软件行业的不断发展&#xff0c;建立一个完善的自动化测试体系变得至关重要。自动化测试包括三个方面&#xff1a;UI前端界面&#xff0c;Service服务契约和Unit底层单元如下图&#xff1a; 越是底层的测试&#xff0c;运行速度越快&#xff0c;时间开销越少&#xff0c;金…

【零参考GAN:Pansharpening】

ZeRGAN: Zero-Reference GAN for Fusion of Multispectral and Panchromatic Images &#xff08;用于多光谱和全色图像融合的零参考GAN&#xff09; 本文提出了一种融合低空间分辨率多光谱(LR MS)和高空间分辨率全色(PAN)图像的新的全色锐化方法–零参考生成对抗网络(ZeRGAN…

(一)、ts 基础类型 及class类举例字符雨和实现vue的挂在#app

文章目录 前言环境执行依赖node.js一、基础数据类型二、任意类型三、接口和对象类型四、 数组类型五、函数重载六、类型断言断言联合类型交叉类型 七、内置对象-Promise基础对象DOM和BOMPromise ts化代码雨案例 八、Class类(派生类和抽象类)派生类 abstract抽象类 classClass简…

自定义SpringBoot启动图标

在SpringBoot项目的resources目录下创建banner.txt文件 在https://www.bootschool.net/网站上复制Ascll艺术字&#xff08;图&#xff09;粘贴到banner.txt中保存。 启动项目就会加载 可以修改颜色&#xff0c;和版本号 ${application.version} 输出版本 ${spring-boot.v…

「软件设计师」 2023年上半年上午真题解析

「软件设计师」 2023年上半年上午真题解析 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &…