• C语言结构体(struct)一些常见问题 ⎛⎝≥⏝⏝≤⎛⎝


    文章目录

    1、结构体的定义以及初始化

    ①定义结构体

     ②对结构体变量进行初始化

    2、结构体在内存中的分配以及字节大小

    ①存储空间如何分配?

     ②结构体所占字节大小如何计算?

    3、结构体指针和结构体变量的区别

    ①结构体指针如何进行访问?

     ②结构体指针和结构体变量的区别

    4、易搞混的结构体指针运算顺序举例


    1、结构体的定义以及初始化

    ①定义结构体

    首先简单定义一个结构体:

    1. struct point {
    2. int x;
    3. int y;
    4. };
    5. //当然你可以写成struct point{int x; int y;}; 都是一样的,缩进不同罢了

    以上代码中,关键字 struct 引入结构声明,结构声明由包含在花括号内的一系列声明组成。

    struct后面的名字是可选的,被称为 结构标记 (这里是point)。 结构标记用于为结构命名,在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式。比如在后面定义结构体变量的时候,就可以写成:

    struct point pt;     //定义了一个结构体变量pt
    

    如果你不想使用结构标记,那么定义变量时你需要把花括号内的声明也写上,写成:

    1. struct{
    2. int x;
    3. int y;
    4. }pt;
    5. //当然你可以写成struct{int x; int y;}pt; 都是一样的,缩进不同罢了

     ②对结构体变量进行初始化

     接下来对结构体变量进行初始化,比如将x赋值为10,y赋值为20:

    1. struct{
    2. int x = 10;
    3. int y = 20;
    4. }pt;

    也可以这样写:

    struct point pt = {10, 20};

    2、结构体在内存中的分配以及字节大小

    ①存储空间如何分配?

    当你定义了一个结构体,且未定义结构体变量时:

    1. struct{
    2. int x;
    3. int y;
    4. };

    则不需要为它分配存储空间,因为它仅仅描述了一个结构的模板或轮廓。结构体变量才包含了实实在在的数据、需要存储空间。

    像下面那样,其中的 struct point pt 就表示声明了一个结构体变量: 

     ②结构体所占字节大小如何计算?

    关于结构体所占的字节大小,需要注意,千万不要认为结构体的长度等于各成员长度的和,因为不同的对象有不同的对齐要求(可以查下关于字节对齐的资料,这里不展开),因此,结构中可能会出现未命名的“空穴”(hole)。例如以下代码:

    1. #include
    2. struct point
    3. {
    4. char x; //char占1个字节
    5. int y; //int占4个字节
    6. };
    7. int main() {
    8. struct point pt;
    9. printf("%d", sizeof pt); //输出8而不是5
    10. return 0;
    11. }

    这里的存储空间需要8个字节而不是5个。

    3、结构体指针和结构体变量的区别

    ①结构体指针如何进行访问?

    如果传递给函数的结构很大,使用指针方式的效率通常比复制整个结构的效率要高。结构体指针类似于普通变量指针:

    struct point *pp

    以上一句,将pp定义为一个指向struct point类型对象的指针,注意上述定义只说明了pp指针指向的对象类型是struct point类型,并未指向point这个结构,所以还访问不了point结构里的成员。那么想要正确访问point中的成员,得记得让指针指向point结构,比如下面这样:

    1. #include
    2. struct point
    3. {
    4. int x = 10;
    5. int y = 20;
    6. };
    7. int main() {
    8. struct point pt; //声明一个结构体变量
    9. struct point *pp; //声明一个结构体指针
    10. pp = &pt; //让指针指向point结构,这样才能进行后续对结构体成员的访问
    11. printf("%d", (*pp).x); //输出10
    12. return 0;
    13. }

    下面来解释下访问方式 (*pp).x ,其中圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级高,表达式*pp.x的含义等价于*(pp.x),因为x不是指针,所以该表达式是非法的。

    当然还有其它访问方式,如下:

    1. //p->结构成员
    2. printf("%d", pp->x); //输出10

    ②结构体指针和结构体变量的区别

    现在来说下结构体指针和结构体变量的区别:

    1.内存空间上面的差别

    假设有如下代码:

    1. struct Stu
    2. {
    3. int age;
    4. }*p, q;

    结构体指针p是指向一个结构体的,如果需要使用这个结构体就必须malloc一个空间出来或者将一个具有空间的结构体的首地址赋予它;如果你不给它分配空间代表这是一个野指针,访问的时候会出错;而结构体变量q,在定义变量的时候,编译器就自动给变量分配了合适的储存空间。

    2.访问上的差别
    结构体指针访问成员变量的操作符是 “->”,结构体变量访问成员变量的操作符是“.”
    指针想用“.”操作符,得写成(*p).age <=> p->age;

    4、易搞混的结构体指针运算顺序举例

    比如以下代码,重点关注下其中的 ++pp->x 的输出:

    1. #include
    2. struct point
    3. {
    4. int x = 10;
    5. int y = 20;
    6. } *pp;
    7. int main() {
    8. struct point pt;
    9. pp = &pt;
    10. printf("%d", ++pp->x); //输出11
    11. return 0;
    12. }

    表达式

    ++pp->x;

    将增加x的值,而不是增加pp的值,这是因为,“->”的优先级比自增“++”更高!所以这里的隐含关系相当于++(pp->x)

    补充一张运算符优先级参考截图(1级比2级先执行):

  • 相关阅读:
    Java的进化之路走到了尽头
    【工具】Sublime配置Anaconda的Python环境的简单方法
    接雨水-热题 100?-Lua 中文代码解题第4题
    Figma UI UX设计教程
    AD20绘制电路板的外形
    flannel安装(二进制安装)
    tomcat web.xml文件中的session-config
    页面打印功能,单选框多选框选中后,打印时不显示选中效果
    企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图
    【QT】创建第一个QT程序
  • 原文地址:https://blog.csdn.net/m0_56494923/article/details/126468496