问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

结构体的介绍

创作时间:
作者:
@小白创作中心

结构体的介绍

引用
CSDN
1.
https://blog.csdn.net/zl_dfq/article/details/144485764

目录
结构体的定义:
9.结构体的特殊定义
结构体变量的创建与初始化:
一、结构体变量创建有两种形式:
二、结构体的初始化:
圆点操作符:
结构体成员的访问:
结构体的自引用 :
结构体的内存对齐:
对齐原因:
修改默认对齐数:
结构体传参 :

结构体的定义:

struct 结构名
{
  类型名 结构成员名1;
  类型名 结构成员名2;
  类型名 结构成员名3;
};
  1. 定义一个结构体,需要用到struct这个关键字
  2. 结构名是自己起的名字,尽量取得有意义
  3. struct 结构名一起构成新的数据类型
  4. 存放在结构体里面的值,叫作成员变量
  5. 结构体的定义以分号结束,C语言把结构体的定义看成是一条语句
  6. 从上面的例子可以看出结构体可以嵌套定义
  7. 定义一个结构体,相当于声明了一个新的数据类型,编译器不会为其分配内存空间,编译器只会为结构体变量分配内存空间
  8. 结构体的作用域根据它的定义位置决定:
  • 当在所有函数外部定义结构体时,它具有全局作用域
    struct Student {
        char name[20];
        int age;
    };
    int main() {
        struct Student stu;
        // 可以在这里使用结构体Student定义变量stu
        return 0;
    }
    
  • 结构体也可以在函数内部或者复合语句(用花括号{}括起来的代码块)内部定义,此时它具有局部作用域。例如
    int main() {
        struct {
            char hobby[20];
            int level;
        } interest;
        // 可以在这里使用结构体变量interest
        return 0;
    }
    

9.结构体的特殊定义

  1. 结构体省去结构名,形成匿名结构体类型,此时结构体变量应在定义结构体时就创建
  2. 此类结构体一般只用一次
  3. 当同时创建多个匿名结构体类型的时候,编译器认为它们的类型并不相同
    struct
    {
        double x;
        double y;
    }m = {1,2};
    struct
    {
        double x;
        double y;
    }*p;
    p = &m;
    

结构体变量的创建与初始化:

一、结构体变量创建有两种形式:

struct point
{
    double x1;
    double y1;
}n;
struct point m;
  1. 在声明结构体时,同时定义变量n,
  2. 单独一行,定义变量m,

二、结构体的初始化:

struct point1
{
    double x1;
    double y1;
}n1 = {3,2};
struct point m1 = {1,5};
----------------------------------------------
struct point2
{
    double x2;
    double y2;
}n2 = {.y2=8, .x2=6};
struct point m2 = {.y2=7, .x2=0};
-----------------------------------------------
struct points
{
    double x1;
    double y1;
    struct point1
    {
        double x2;
        double y2;
    };
}m = { 1,2,{3,4} };
  1. 第一种初始化是按顺序初始化,此时
  • 对于n1变量来说, x1 == 3 y1 == 2
  • 对于m1变量来说, x1 == 1 y1 == 5
  1. 第二种初始化是按指定顺序初始化,此时需要用到 .成员选择操作符(圆点操作符)此时
  • 对于n2变量来说, x2 == 6 y2 == 8
  • 对于m2变量来说, x2 == 0 y2 == 7
  1. 第三种初始化时结构体嵌套初始化,此时只是不要忘记将结构体变量初始化要用到花括号即可

圆点操作符:

  1. 该操作符的操作数是两个,即 结构变量名.成员名
  2. 初始化的时候可以省去结构变量名

结构体成员的访问:

上述的圆点操作符可以很直接的访问我们所需要的成员变量,但是
通过指针我们也可以对相应成员变量进行访问
1)使用方式:结构体指针->成员名

结构体的自引用 :

多个的结构体变量,想要从上一个结构体变量访问下一个结构体变量时,

struct point1
{
    double x1;
    double y1;
    struct point1* p;
};
------------------------------
struct point2
{
    double x2;
    double y2;
    struct point2 next;
};
  1. 虚线上方,结构体既包含了数据型的成员变量,也包含了一个结构体类型的的地址,通过结构体变量初始化,便可以通过指针访问到下一个结构体变量
  2. 虚线下方,结构体包含了数据型的成员变量,也包含了一个结构体,似乎,顺理成章地就可以通过上一个结构体变量访问下一个结构体变量,但是,一个包含一个,那它究竟有多大呢,无从而知,所以编译器无法为其分配合适的空间,这种定义就不合法

结构体的内存对齐:

(此总结来源:鹏哥c语言)

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对 齐数=编译器默认的一个对齐数与该成员变量大小的较小值。
    VS 中默认的值为 8-
    Linux中gcc没有默认对齐数,对齐数就是成员自身的大小
  3. 结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最 大的要与默认对齐数比较并取较小值)的 整数倍
  4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最 大对齐数的整数倍处,结构 体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍
  5. 让占用空间较小的变量尽量集中到一起以节省空间

对齐原因:

(1)性能原因:现代计算机的处理器在读取内存时,每次读取的数据块大小是固定的(例如,32 位处理器通常以 4 字节为单位读取,64 位处理器通常以 8 字节为单位读取)。如果结构体成员的存储位置不符合对齐要求,处理器在读取这些成员时可能需要进行多次内存访问,从而降低了程序的运行效率。通过结构体对齐,可以保证处理器能够更高效地访问结构体中的成员。
(2)平台(硬件)原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定 类型的数据,否则抛出硬件异常

修改默认对齐数:

结构体传参 :

两种传参形式:传值传参,传址传参

struct point1
{
    double x;
    double a[1000];
    double y;
}m;

我们知道,传值传参时,函数会临时拷贝相应的值,如果传入的值所占内存太大,如上,那么,这既是对空间的消耗,也是对时间的消耗
而传址传参时,函数只需拷贝一份地址,通过地址便可访问相应的值,那么,时间空间的消耗便会大大减少!!
所以,当传入的值所占内存不大时,两种方式皆可,反之,传址传参才是最优选择!

本文原文来自CSDN

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号