闲聊C语言结构体

作者: 罗蓁蓁 | 来源:发表于2021-12-08 10:46 被阅读0次

结构体是 C 语言主要的自定义类型方案,这篇就来认识一下结构体。

一、结构体的形态

C源程序(struct.c):

#include <stdio.h>

typedef struct{
    unsigned short int a;
    unsigned short int b;
}Data;

int main()
{
    Data c, d;
    
    c.a = 1;
    c.b = 2;
    d = c;
    
    printf("d.a:%d\nd.b:%d\n", d.a, d.b);
    return 0;
}

赋值部分翻译后:

    movw    $1, 28(%esp)    # c.a = 1
    movw    $2, 30(%esp)    # c.b = 2
    movl    28(%esp), %eax  #
    movl    %eax, 24(%esp)  # d = c

可以看出:

  • c.a 是在 28(%esp) 之后的2个字节
  • c.b 是在 30(%esp) 之后的2个字节
  • c 是 28(%esp) 之后的4个字节
  • d 是 24(%esp) 之后的4个字节

不得不感叹名字(结构体名字、子元素名字)再一次被抛弃了,子元素名代表的是相对于结构体的偏移。

二、结构体的复制

很早就被告知:数组不能复制!但是当发现下面这个程序正常运行后,我困惑了(block.c):

#include <stdio.h>

typedef struct{
    char data[1000];
}Block;

Block a={{'a','b','c',}};

int main()
{
    Block b;

    b=a;
    
    puts(b.data);
    return 0;
}

Block a={{'a','b','c',}} 是对 a 的部分初始化,'c' 后面自动填 0,写成 Block a={{"abc"}} 也一样,C 语言对初始化还是很宽容的。

上面这个程序居然正常的编译、运行了,这究竟是怎样的逆天?
看看汇编部分:

leal    24(%esp), %edx
movl    $a, %ebx
movl    $250, %eax
movl    %edx, %edi  # edi = &b
movl    %ebx, %esi  # esi = &a
movl    %eax, %ecx  # ecx = 250
rep movsl

我们发现程序确实通过 250 次 movsl 复制了一个"数组"。其原因是:结构体是可以复制的,结构体又可以包括任意类型的子元素,数组也行,所以"数组"也被复制了。

那为什么纯粹的数组就不能复制呢?

我们可以这样去理解:一个变量能被复制的必要条件是我们知道它的大小。结构体做为自定义类型,在编译的时候编译器必然存储了它的子元素类型、个数等相关信息,结构体的大小也就知道了;而数组一般只在乎它的类型和起始地址,元素个数总是被忽视的(例如:void func(char s[]) 可接受任何长度的字符数组做参数),而且元素个数也没有被当做数组的一部分存入内存,所以数组的复制是不好实现的。

三、结构体中的数组和指针

对于结构体中的指针,如果把结构体a赋值给结构体b,那么对于指针来说,只是简单的拷贝指针地址,并不会重新分配一个内存空间,以及新的指针地址。也就是说结构体a和结构体b中的指针,共享空间。
对于结构体中的数组,则恰恰相反,他们并不共享空间,而是重新分配一个内存空间,用以保存数组内容。
我们可以这样去理解:一个变量能被复制的必要条件是我们知道它的大小。因此,在计算结构体大小时,结构体中的指针只占有了四个字节,而数组则占用数组本身的大小,因此,指针只是简单的拷贝指针地址,而数组却可以重新分配一个内存空间来保存数组内容。

四、小结

如果给结构体下一个实在点的定义话,那就是:有格式的字节数组。有了结构体后 C 语言的变量类型就丰富多了,但是同时也要注意:

  1. 超过 4 字节的结构体不宜做参数(参数传递浪费时间、空间),换做指针更好。
  2. 超过 4 字节的结构体不宜做返回值类型(话说一般返回值都用 eax 来存,那么超过 4 字节的时候怎么存呢?自己去探索吧!)。

五、关注&&联系

gitee: https://gitee.com/cmcc-oneos/OneOS-Lite

docs: https://oneos-lite.com/

相关文章

  • 闲聊C语言结构体

    结构体是 C 语言主要的自定义类型方案,这篇就来认识一下结构体。 一、结构体的形态 C源程序(struct.c):...

  • C语言和OC的结构体(struct)

    Struct(结构体) 1.结构体定义 2.结构体变量 3.结构体数组 4.C语言结构体指针 5.C语言共用体 6...

  • C语言结构体用法很多,坑也很多

    C语言可谓是编程界的传奇语言,历经几 十 年,依然排名前列。 本文主要说的是C语言中的结构体,结构体是C语言中重要...

  • C语言结构体

    结构体 本文介绍C语言结构体,struct 在C++中功能相对C较多,相当于类,这里暂时不讨论,本文单独讨论C语言...

  • 嵌入式学习笔记19.11.25

    c语言结构体 结构体一般定义全局变量 struct stu{//struct 定义结构体 stu 结构体名称 in...

  • 12-Go语言结构体

    结构体 结构体的基本概念 什么是结构体Go语言中的结构体几乎和C语言中的结构体一模一样都需要先定义结构体类型, 再...

  • C语言学习笔记-结构体占用内存大小的计算

    引言 结构体在C语言中虽然经常使用,但是怎么计算一个结构体占用多大的内存,很多C语言的新手都没注意过,其实C语言的...

  • 结构体与指针

    1.1 Linux C语言结构体 简介:本课程深入的讲解了C语言中,预处理是怎么回事,结构体和公用体又是如何使用及...

  • c语言中的结构体

    结构体是 C 语言主要的自定义类型方案,这篇就来认识一下结构体。 一、结构体的形态 C源程序(struct.c):...

  • 深入理解Runtime中的isa

    objc_object Objective-C 所有对象都是 C 语言结构体objc_object,这个结构体中包...

网友评论

    本文标题:闲聊C语言结构体

    本文链接:https://www.haomeiwen.com/subject/nvttfrtx.html