zoukankan      html  css  js  c++  java
  • C 语言结构体 struct 及内存对齐

    struct 结构体

    对于复杂的数据类型(例如学生、汽车等),C 语言允许我们将多种数据封装到一起,构成新类型。

    跟面向对象语言中的对象相比,结构体只能包含成员变量,不支持操作。

    #include <stdio.h>
    #include <string.h>
    
    struct People
    {
    	int age;
    	char name[100]; // 这里如果用指针,下面用 strcpy 赋值时会报段错误
    }; // 分号必须有
    
    int main()
    {
    	struct People p = {20, "lisi"}; // 使用时,struct People 是一个整体
    	printf("%d, %s
    ", p.age, p.name); // 用点访问结构体成员
    	struct People *pp = &p;
    	pp->age = 88;
    	strcpy(pp->name, "jack"); // C 语言需要用 strcpy 函数实现字符串拷贝
    	printf("%d, %s
    ", p.age, p.name);
    
    	return 0;
    }
    

    结构体成员变量的两种访问方式

    用句点形式访问(结构体变量)

    结构体变量声明后,可以直接用句点形式访问。

    struct People p = {20, "lisi"};
    p.age = 88;
    

    用箭头访问(结构体指针变量)

    定义指向结构体的指针后,可以通过箭头来访问成员变量。

    struct People p = {20, "lisi"};
    struct People * pp = &p;
    pp->age = 88; // 等价于 (*pp).age
    

    内存对齐

    对于 32 位数据总线的机器(例如 80386),虽然对内存仍然是按照字节寻址,但每次内存操作都固定传输 32 位数据。如果每次数据传输都连续且不重叠,效率是最高的。所以操作系统把内存按照数据总线的位数划分为独立单元,对于 32 位数据总线的机器每个单元是 4 个字节。每个单元都完整的分配给一个程序。

    C 语言的 struct 结构体中,可以放各种类型、不同长度的数据,可以看做一个数据包。为了在程序内部提高内存访问效率,也需要对齐内存。

    下面的示例,struct People 中的第一个变量 sex 会对齐内存,第二个变量 age 紧随其后,总共占了三个字节,空余一个字节。之后的 no 占用 4 个字节,如果直接放在 sex 后面保存,则访问 no 时需要两次对内存的操作。为了提高时间效率,C 编译器会把 no 变量对齐内存,这样 no 跟 sex 之间会有一个字节的空白。

    #include <stdio.h>
    
    struct People {
    	char sex; // 1 字节
    	short age; // 2 字节,此时两字节对齐,前面空一个字节
    	int no; // 4 字节,此时4字节对齐,前面空一个字节
    };
    
    int main()
    {
    	struct People p = {'m', 66, 1234567};
    	printf("%d
    ", sizeof(p)); // 8 个字节
    }
    

    下面的例子中,少了一个变量,但因为字节对齐的原因,存储空间并没有减少:

    #include <stdio.h>
    
    struct People {
    	char sex; // 1 个字节
    	int no; // 4 个字节,前面空 3 个字节
    };
    
    int main()
    {
    	struct People p = {'M', 1234567};
    	printf("%d
    ", sizeof(p)); // 还是 8 个字节
    }
    

    而这个例子中,因为结构体中变量的顺序发生改变,导致空间膨胀:

    #include <stdio.h>
    
    struct People {
    	char sex; // 1 个字节
    	int no; // 4 个字节,前面空 3 个字节
    	short age; // 2 个字节,后面空 2 个字节
    };
    
    int main()
    {
    	struct People p = {'m', 1234567, 66};
    	printf("%d
    ", sizeof(p)); // 这里是 12 个字节
    }
    
  • 相关阅读:
    Mplayer 音频解码分析
    U盘安装Centos6.3
    U盘安装Centos6.3
    Mplayer 音频解码分析
    Java 基础代码实例 :判断顾客对商品折扣的反应情况。
    Java 基础源码 switch语句判断指定月份属于一年中的哪个季度
    Java 交换值算法 不用中间变量,换运算
    Java基础二维数组代码实例
    private 成员变量 局部变量
    Java继承的基本概念及其限制 总结
  • 原文地址:https://www.cnblogs.com/kika/p/10851508.html
Copyright © 2011-2022 走看看