zoukankan      html  css  js  c++  java
  • 深入理解 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
    ",sizeof(char_var));
    	printf("sizeof float = %d
    ",sizeof(float_var));
    	printf("sizeof double = %d
    ",sizeof(double_var));
    	printf("sizeof long double = %d
    ",sizeof(ldouble_var));
    	printf("sizeof int = %d
    ",sizeof(int_var));
    	printf("sizeof long long = %d
    ",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
    ",sizeof(char_point));
    	printf("sizeof pdouble = %d
    ",sizeof(double_point));
    	printf("sizeof pint = %d
    ",sizeof(int_point));
    	printf("sizeof plong long = %d
    ",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
    ",sizeof(char_arr));
    	printf("sizeof arrdouble = %d
    ",sizeof(double_arr));
    	printf("sizeof arrint = %d
    ",sizeof(int_arr));
    	printf("sizeof arrlong long = %d
    ",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
    ",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) 啦!(丝毫没用)

  • 相关阅读:
    回车换行解释
    二,php的错误处理
    2017年计划
    postgresql无法安装pldbgapi的问题
    在tmux中的vi 上下左右键变为了ABCD等字符
    查看某表有没有语句被锁住
    ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock
    PostgreSQL杀掉死锁的链接
    实现从Oracle增量同步数据到GreenPlum
    终于将rsync-3.1.2配置成功,之外还挖掘了一些新的用法
  • 原文地址:https://www.cnblogs.com/zhwer/p/12294903.html
Copyright © 2011-2022 走看看