深入理解 C/C++ sizeof() 运算符
过去有一段时间一直以为带个括号的 \(sizeof()\) 是 \(C/C++\) 的原生函数QAQ。
其实不然,\(sizeof\) 同位运算符(^|&~!)一样是一种单目运算符,作用于变量或数组。
在编译时编译器就会把 \(sizeof()\) 的内容转换成常数存入机器码中,不涉及函数的底层操作。
用途
sizeof 运算符可用于获取类、结构、共用体和其他用户自定义数据类型的大小。
使用 sizeof 的语法如下:
sizeof (data type)
其中,data type 是要计算大小的数据类型,包括类、结构、共用体和其他用户自定义数据类型。
sizeof 与 普通变量
#include<bits/stdc++.h>
using namespace std;
int main() {
char char_var;
float float_var;
double double_var;
long double ldouble_var;
int int_var;
long long ll_var;
printf("sizeof char = %d\n",sizeof(char_var));
printf("sizeof float = %d\n",sizeof(float_var));
printf("sizeof double = %d\n",sizeof(double_var));
printf("sizeof long double = %d\n",sizeof(ldouble_var));
printf("sizeof int = %d\n",sizeof(int_var));
printf("sizeof long long = %d\n",sizeof(ll_var));
return 0;
}
输出结果:
sizeof char = 1
sizeof float = 4
sizeof double = 8
sizeof long double = 16
sizeof int = 4
sizeof long long = 8
可以看出,编译器把 sizeof 的内容都替换成了变量占用的空间大小(单位为字节)。
此外,作为一个运算符,在 sizeof 之后的变量名可以不用括号括起来,这样在概念上就不会和函数混淆了。
sizeof 与 指针变量
#include<bits/stdc++.h>
using namespace std;
int main() {
char *char_point;
double *double_point;
int *int_point;
long long ll_point;
printf("sizeof pchar = %d\n",sizeof(char_point));
printf("sizeof pdouble = %d\n",sizeof(double_point));
printf("sizeof pint = %d\n",sizeof(int_point));
printf("sizeof plong long = %d\n",sizeof(ll_point));
return 0;
}
输出结果:
sizeof pchar = 8
sizeof pdouble = 8
sizeof pint = 8
sizeof plong long = 8
所有类型的指针变量在 \(32\) 位环境中占用四字节,在 \(64\) 位环境中占用 \(8\) 字节。
我的编译器是 \(x64\)( \(64\) 位)的,如果是 \(x86\) 编译器( \(32\) 位)下输出结果应该是 \(4\) 。
sizeof 与 数组
#include<bits/stdc++.h>
using namespace std;
int main() {
char char_arr[10]="233";
double double_arr[10]={0.0};
int int_arr[10]={0,1,2,3,4,5,6,7,8,9};
long long ll_arr[10];
printf("sizeof arrchar = %d\n",sizeof(char_arr));
printf("sizeof arrdouble = %d\n",sizeof(double_arr));
printf("sizeof arrint = %d\n",sizeof(int_arr));
printf("sizeof arrlong long = %d\n",sizeof(ll_arr));
return 0;
}
输出结果:
sizeof arrchar = 10
sizeof arrdouble = 80
sizeof arrint = 40
sizeof arrlong long = 80
sizeof 与结构体
#include<bits/stdc++.h>
using namespace std;
int main() {
struct Student {
char name[20];
bool sex;
int age;
int num;
}stu;
printf("sizeof (Student)stu = %d\n",sizeof(stu));
return 0;
}
输出结果:
sizeof (Student)stu = 32
name数组占用 \(1*10=20\) 个字节,两个int占用 \(4*2=8\) 个字节,一个bool占用 \(1\) 个字节,加起来应该是 \(29\) 。
而程序输出了 \(32\) ,是不是编译器出问题了?
其实这是正常的,因为结构体的成员变量占用的是一块连续的内存,但是为了保证对不同类型的变量寻址正确,编译器会在储存各变量地址时自动对齐,而不是每个变量的内存块都紧密相连。
计算结构体大小需要了解一个名词偏移量,即结构体变量中成员的地址与结构体首地址的差(首个成员的地址),结构体内容每个成员(包括成员变量、函数、嵌套体)都拥有这一属性。
结构体内偏移量的计算公式为:上一个成员的偏移量 + 上一个成员的占用字节数
为了做到成员地址的对齐,编译器在编译程序时会遵照如下规则:
结构体变量中成员的偏移量必须是该成员大小的整数倍,否则向上补齐
还是用上面的例子,
\(name[20]\) 为首元素,偏移量为 \(0\) 。
\(sex\) 偏移量为 \(0 + 20 = 20\),\(20 \% 1 = 0\) ,无须补齐。
\(age\) 偏移量为 \(20 + 1 = 21\),\(21 \% 4 ≠ 0\),偏移量向上补齐为整除 \(4\) 的 \(24\)。
\(num\) 偏移量为 \(24 + 4 = 28\),\(28 \% 4 = 0\) ,无须补齐。
最后算出该结构体占用的内存大小为 = num的偏移量 + num占用的大小 = \(32\) 字节。
根据结构体变量地址对齐的这一特性,还可以知道在结构体中,结构体成员变量写的顺序会影响该结构体占用的空间大小。
根据简单的数学知识,把内存占用较小的结构体成员写在前面是比较优秀的。
此外,结构体标准对齐值也可以自定义,具体操作可以参考这篇博客。
最后,下次写 \(memset\) 的参数就可以不用写算出占用的空间而不用 \(sizeof\) 啦!(丝毫没用)
深入理解 C/C++ sizeof() 运算符的更多相关文章
- 深入理解类成员函数的调用规则(理解成员函数的内存为什么不会反映在sizeof运算符上、类的静态绑定与动态绑定、虚函数表)
本文转载自:http://blog.51cto.com/9291927/2148695 总结: 一.成员函数的内存为什么不会反映在sizeof运算符上? 成员函数可以被看作是类 ...
- C++(十五) — sizeof 运算符
1.基本数据类型 sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小. sizeof 运算符可用于获取类.结构.共用体和其他用户自定义数据类型的大小. 使用 sizeo ...
- C++ sizeof 运算符
sizeof 是一个关键字,它是一个编译时运算符,用于判断变量或数据类型的字节大小. sizeof 运算符可用于获取类.结构.共用体和其他用户自定义数据类型的大小. 使用 sizeof 的语法如下: ...
- Sizeof运算符小结
以下内容援引自<C Primer Plus>中文版第五版Page95 Sizeof运算符以字节为单位返回其操作数的大小.(在C中,1个字节被定义为char类型所占用空间的大小.在过去,1个 ...
- sizeof运算符和strlen函数的区别
1.sizeof是运算符,而strlen是函数. 2.sizeof操作符的运算结果为size_t,他在头文件中的typedef为unsigned int.该类型保证能容纳所操作对象的最大字节大小. 3 ...
- 坑爹系列:sizeof运算符
C语言里的sizeof关键字用于返回变量的类型宽度(变量所占的字节个数).例如: #include <stdio.h> int main() { int i = 0; int size = ...
- sizeof运算符来获取各种数据类型在内存中所占字节数--gyy整理
C++并没有规定各种数据类型在内存中的存储大小,依赖于不同的编译器的不同而不同,要想获知当前编译器对各种数据类型分配的大小,可以通过sizeof运算符来获取. 使用方法1: sizeof(数据类型) ...
- sizeof运算符
sizeof运算符返回一条表达式或一个类型名字所占的字节数.sizeof运算符满足右结合律,其所得的值是一个size_t类型的常量表达式.运算符的运算对象有两种形式: sizeof(type) siz ...
- C++ Prime:sizeof运算符
sizeof运算符的结果部分地依赖于其作用的类型: 对char或者类型为char的表达式执行sizeof运算结果得1: 对引用类型执行sizeof运算得到被引用对象所占空间的大小: 对指针执行size ...
随机推荐
- 创建一个圆类Circle的对象,分别设置圆的半径计算并分别显示圆半径、圆面积、圆周长。
编写一个圆类Circle,该类拥有: ①一个成员变量 Radius(私有,浮点型): // 存放圆的半径: ②两个构造方法 Circle( ) // 将半径设为0 Circle(double r ) ...
- Actix-web Rust连接Postgres数据库
Actix-web Rust连接Postgres数据库 Rust1.39支持了异步async,await,Actix-web在2.0.0-alpha支持了原生异步写法,所以本文中使用的Actix- ...
- python中元类(metaclass)的理解
原文地址:http://www.cnblogs.com/tkqasn/p/6524879.html 一:类也是对象 类就是一组用来描述如何生成一个对象的代码. 类也是一个对象,只要你使用关键字clas ...
- Codeforces_446_B
http://codeforces.com/problemset/problem/446/B 分别将每行的和与每列的和存入优先队列,计算操作n次的最大和,保存每一次结果. 枚举行和列操作的次数,注意要 ...
- HDU3836 Equivalent Sets (Tarjan缩点+贪心)
题意: 给你一张有向图,问你最少加多少条边这张图强连通 思路: 缩点之后,如果不为1个点,答案为出度为0与入度为0的点的数量的最大值 代码: #include<iostream> #inc ...
- 春招必问的redis持久化(RDB AOF),你能答上来么?
春招面试模拟,如同雷同,纯属巧合!!! 面试的大体流程: 第一步:一般会有笔试题,也可能没有.有笔试题就要好好答了,因为会重视笔试结果,为了节约面试官时间,HR可能先会看,不合格直接让你走人了. 第二 ...
- Golang调用Dll案例
Golang调用Dll案例 前言 在家办公已经两个多星期了,目前最大的困难就是网络很差.独自一个人用golang开发调用dll的驱动程序.本来就是半桶水的我,还在为等待打开一个页面而磨平了耐心.本想依 ...
- c#设计模式读书博客
第一次在博客园撸博客,也是为了鞭策自己去学习进步,过年之后买了一本<C#设计模式>这是我一直很想去学习的一本书.然后用博客记录我的学习历程,并且分享给需要的人.这本书记录的设计模式有23种 ...
- python pandas合并多个excel(xls和xlsx)文件(弹窗选择文件夹和保存文件)
# python pandas合并多个excel(xls和xlsx)文件(弹窗选择文件夹和保存文件) import tkinter as tk from tkinter import filedial ...
- python安装模块速度慢的解决方法
1.Win+R,cmd 2.pip install pqi 3.pqi use aliyun