结构体

7.1 概念

  • 结构体可以理解为自定义的数据类型
  • 是由一批数据组合而成的结构型类型
  • 里面的每一个数据都是结构体的“成员”

7.2 示例

可以写在函数的里面和外面

#include <stdio.h>
#include <string.h>		//提供strcpy函数

int main(){
    //定义结构体
    struct person{
	    char name[100];
	    int age;
	    double height;
    };

    //定义结构体变量
    struct person per1;
    strcpy(per1.name, "zhangsan");
    per1.age = 18;
    per1.height = 1.88;

    struct person per2;
    strcpy(per2.name, "lisi");
    per2.age = 20;
    per2.height = 1.78;
  

    //打印结构体变量
    printf("name:%s\n",per1.name);
    printf("age:%d\n",per1.age);
    printf("height:%lf\n",per1.height);

    printf("\n");

    printf("name:%s\n",per2.name);
    printf("age:%d\n",per2.age);
    printf("height:%lf\n",per2.height);
   
    return 0;
}

定义的时候可以同时赋值

struct person per1 = {"zhangsan",18,1.88};
struct person per2 = {"lisi",20,1.78};

7.3 结构体数组

把per1和pe2放入一个数组中去

struct person perarr[2] = {per1, per2}; 

遍历数组并打印

for(int i = 0; i < 2; i++){
	printf("name:%s\n",perarr[i].name);
	printf("age:%d\n",perarr[i].age);
	printf("height:%lf\n",perarr[i].height);
}

7.4 起别名

适用于觉得写 struct和结构体名字很麻烦的情况
使用 typedef进行别名设置

typedef struct person{		//person可省略不写
	char name[100];
	int age;
	double height;
} P;	//P即为person结构体的别名

之后的定义可直接使用别名,并省略 struct

P per1 = {"zhangsan",18,1.88};
P per2 = {"lisi",20,1.78};

完整代码:

#include <stdio.h>
#include <string.h>

int main(){
    //定义结构体
    typedef struct jie
    {
	    char name[100];
	    int age;
	    double height;
    } P;

    //定义结构体变量

    P per1 = {"zhangsan",18,1.88};		//P
    P per2 = {"lisi",20,1.78};			//P

    //打印结构体变量
    printf("name:%s\n",per1.name);
    printf("age:%d\n",per1.age);
    printf("height:%lf\n",per1.height);

    printf("\n");

    printf("name:%s\n",per2.name);
    printf("age:%d\n",per2.age);
    printf("height:%lf\n",per2.height);

    P perarr[2] = {per1, per2}; 		//P

    for(int i = 0; i < 2; i++){
        printf("\n");
        printf("name:%s\n",perarr[i].name);
        printf("age:%d\n",perarr[i].age);
        printf("height:%lf\n",perarr[i].height);
    }
   
    return 0;
}

7.5 结构体作为函数的参数进行传递

  • 传递结构体中的数据值(新的变量)
#include<stdio.h>

typedef struct number{
    int n1;
    int n2;
}N;

int add(int int1, int int2);

int main(){
    N number1 = {3, 9};
    N number2 = {23, 23}; 
    N number3 = {2, 12};
    N number4 = {12, 12};

    N numarr[] = {number1, number2, number3, number4};

    for(int i = 0; i < 4; i++){
        printf("%d\n", add(numarr[i].n1, numarr[i].n2));
    }

    return 0;

}

int add(int int1, int int2){
    return int1 + int2;
}
  • 传递结构体的地址值(对原变量有影响)
#include <stdio.h>
#include <string.h>

//定义结构体
typedef struct Person
{
    char name[100];
    int age;
    double height;
} P;

//定义函数
void method(P* p);      //这行代码必须写在结构体定义之后,因为在结构体定义之后,编译器才知道S是社么东西



int main(){
    //定义结构体变量
    P per1 = {"zhangsan",18,1.88};
    P per2 = {"lisi",20,1.78};

    //打印结构体变量
    printf("name:%s\n",per1.name);
    printf("age:%d\n",per1.age);
    printf("height:%lf\n",per1.height);

    printf("\n");

    printf("name:%s\n",per2.name);
    printf("age:%d\n",per2.age);
    printf("height:%lf\n",per2.height);

    P perarr[2] = {per1, per2}; 

    for(int i = 0; i < 2; i++){
        printf("\n");
        printf("name:%s\n",perarr[i].name);
        printf("age:%d\n",perarr[i].age);
        printf("height:%lf\n",perarr[i].height);
    }

    //调用函数
    method(&per1);	//需要闯入地址


    return 0;
}

void method(P* p){//指针p里面记录的是per1的地址
    printf("Get the first data: %s,%d,%lf\n", (*p).name, (*p).age, (*p).height);
    //修改
    printf("pls input the name that you want to change:\n");
    scanf("%s", (*p).name);
    printf("pls input the age that you want to change:\n");
    scanf("%d", &(*p).age);
    printf("pls input the height that you want to change:\n");
    scanf("%lf", &(*p).height);
    printf("Get the second data: %s,%d,%lf\n", (*p).name, (*p).age, (*p).height);

}

如果在传递的时候不适用指针传递,是不会对原来的变量产生影响的,是新建了一个局部变量

7.6 结构体嵌套

typedef struct num1{
	int n1;
	int n2;
	int n3;
}  N1;

N1 number1 = {23, 76, 12};

typedef struct num2{
	int n1;
	int n2;
	int n3;
	N1 number1; 
};
//对结构体里面的结构体赋值
struct num2 number2.number1.n3 = 12;
//批量进行赋值
struct num2 number2 = {12, 345, 123, {12, 89, 34}};

7.7 结构体内存对齐

struct num{
	double a;	//8个字节
	char b;		//1个字节 + 3个空白字节
	int c;		//4个字节
	char d;		//1个字节 + 7个空白字节
};		//共占24个字节
  1. 在结构体的存储中,不同的变量不是紧挨着存储的
  2. 在确定变量位置时,变量只能放在自己类型整数倍的内存地址上
  3. 中间没有存储变量的地方存储空白字节
  4. 最后一个补位:结构体的总大小,是最大类型的整数倍

如下表所示

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
a a a a a a a a b \0 \0 \0 c c c c d \0 \0 \0 \0 \0 \0 \0