C语言-汇编-结构体

时间:2023-03-16 22:54:52

C语言结构体:

数据类型 数据大小
char 1字节
short 2字节
int 4字节
float 4字节
double 8字节
longlong 8字节
数组 自己设置
结构体 自己设置

在我们存储数据时,往往根据数据大小来选择数据类型。当我们要设置一组数据进行存储的时候基础的数据类型就无法满足我们的要求了,我们就开始考虑数组或者是结构体。数组与结构体的区别在哪儿?区别就在数组存储的是同一个类型的数据,而结构体可以存储多个类型的数据

结构体

struct person1{
    char name;
    int age;
    char sex;
    float hight;
    float wieght;
    short appearance;
    int arr[10];
}
//或者
struct font{
    char name;
    char sex;
}
struct number{
    float hight;
    float wieght;
}
struct person2{
    struct font a;
    struct number b;
    int age;
    short appearance;
}
person1 q;
int main(){
    person2 w; 
    struct q.name='a';
    struct q.sex=0;
    struct q.arr[2]=5;
    struct w.font.a='k';
    struct w.number.b='l';
}

全局变量的特点就是在编译时,变量的地址就确定好了。而全局变量中的数组和结构体的区别:

数组:连续分配的地址单元,分配的地址单元等大

结构体:连续分配的地址单元,分配的地址单元不一定等大

结构体存储的特点

  • 结构体会更节省存储空间

​ 没有用结构体声明的变量,它的存储会更占空间。这是因为单独声明的局部变量它并没有连续的分配地址空间,它会用两个堆栈地址单元来分隔变量,而结构体则是连续的地址分配。单独声明的变量都是从低地址开始存先声明的数据,但是数组和结构体都是从高地址开始存储先声明的数据。(这反而可以解释为什么单独声明的数据要在结构体前面而不能放在结构体后面)

  • 可以存储不同类型的数据
struct aa{
	char a;
	short b;
	int c;
};
int main(){
	 struct aa x;
	 x.a=1;
	 x.b=2;
	 x.c=3;
}
//对应反汇编
/*
mov byte ptr ss:[ebp-c],1
mov eax,2
mov word ptr ss:[ebp-a],ax
mov dword ptr ss:[ebp-8],3
*/

1、唯一能判断是结构体的方法就是,如果它把数据分配在堆栈连续的地质单元中,且个数据的类型不全相同,这就代表它是一个结构体。此外和数组没有任何区别

2、short型(0001对应ax寄存器)的数据会用寄存器进行存储,

  • 结构体的空间分配

​ 在我们调用结构体的时候,我们所分配的空间就已经决定好了。结构体的内存大小是根据我们所设置的结构体中的变量数和变量类型所进行分配的。即使我们在使用该结构体时没有用到所有的变量。这里也是结构体和数组之间的一个区别,结构体是不会补零,将未使用到的变量进行填充占位。(我想应该可以通过给堆栈分配的空间大小和声明的变量数等来推测数据类型,仅是理论)

C语言-汇编-结构体

结构体中声明数组,和直接声明数组变量基本是没有区别的。要说有,那就是这个数组是没有补零的。而且是可以按照数组下标随意填赋值的。(这里也可以进行数组越界哦!)

小结:无论是结构中的基本数据类型,还是数组、结构体,其基本特点都是一样的。

  • 结构体作为全局变量时

​ 结构体如果在函数外进行声明,那么它的地址就会在内存中分配好,不会把数据存储到堆栈中。

  • 结构体作为传参时

​ 结构体作为传参时,是通过寄存器进行的。他会先存入寄存器中,再通过寄存器压栈将数据传入堆栈中。当然如果我们设置了太多的变量,那么他会直接去提升堆栈将存入堆栈中的数据直接变成参数。(这是结构体在函数内声明时的情况)如果是声明的全局变量的结构体,那么它一样通过寄存器压栈进行传参,数据太多就先提升堆栈,再通过寄存器一个一个进行入栈操作。

C语言-汇编-结构体C语言-汇编-结构体C语言-汇编-结构体C语言-汇编-结构体

小结:结构体作为传参都是先存入寄存器之后再进行的压栈操作,当结构体中的变量太多时,会选择直接提升堆栈创建空间来简化操作。(还是要用到寄存器进行压栈传参)

关键字sizeof:C语言中用于显示数据类型的关键字。

字节对齐(结构体对齐)

​ 在创建结构体时,我们声明变量的顺序不同,结构体所占用的空间不同。这就是因为结构对齐。

本质:选择效率还是空间

字节对齐规则

1、每个数据成员要存储在该成员的大小的整数倍开始(起始为0)

2、结构体的总大小必须是其内部最大成员的整数倍,不足的要补齐

3、在结构体嵌套中,结构体的大小是其内部最大成员的大小

C语言知识补充

//typedef关键字:对已有数据类型定义别名
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int dword;

typedef int arr[10]
int main(){
    arr x;
    x[0]=1;
    x[1]=2;
    x[2]=3;
}
//定义结构体数组
typedef struct aa{
    char a;
    short b;
    int c;
}x;
x.arr[10];
int main(){
    arr[1]=1;
    arr[2]=2;
    arr[3]=3;
}