IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言-结构体 -> 正文阅读

[C++知识库]C语言-结构体

结构体struct

C语言中,结构体类型属于一种构造类型(其他的构造类型还有:数组类型,联合类型)。

为什么要有结构体?1

在实际问题中,一组数据往往有很多种不同的数据类型。例如,登记学生的信息,可能需要用到 char型的姓名,int型或 char型的学号,int型的年龄,char型的性别,float型的成绩。

使用结构体是解决多类型数据集合存放的问题

结构体声明

struct 结构名{
成员列表
};

struct关键词表示接下来是一个结构。

struct Student{         //声明结构体
    char name[20];      //姓名
    int num;            //学号
    float score;        //成绩
    void (*pintroduce)(char *pname); //行为:函数指针
};

结构体定义

struct 结构体名 结构体变量名;

struct Student stu1;    //定义结构体变量

结构体变量的初始化

stu1 = {"Tom", 15, 88.0}; 
strcpy(stu1.name, "Jack");
stu1.num = 18;
stu1.score = 90.5;

访问结构成员

结构变量名 . 成员名

stu1.name //表示学生stu1的姓名

结构体基础应用案例

#include <stdio.h>
#include <stdlib.h>

struct Student{
    char name[20];   //名字
    int score;   //分数
    //根据不同业务需求,存放不同的数据类型
};

int main()
{
	struct Student stu1 = {"木易杨",100};
    
    printf("结构体:name = %s\n",stu1.name);
    printf("结构体:score = %d\n",stu1.score);
    
    struct Student test;
    //test.name = "弓长张";
    //C语言不能这样写,不能直接给数组名赋值,因为数组名是一个常量
    strcpy(test.name,"弓长张");
    test.score = 60;
    
    printf("test:name = %s\n",test.name);
    printf("test:score = %d\n",test.score);
    
    system("pause");
    return 0;
}

执行结果:

结构体:name = 木易杨
结构体:score = 100
test:name = 弓长张
test:score = 60

结构体整合数据类型案例应用

#include <stdio.h>
#include <stdlib.h>

void func(int data)
{
	printf("函数:data = %d\n",data);
}

struct Datas{
	int a;
    char c;
    float f;
    double d;
    char str[128];
    void (*p)(int a);
};

int main()
{
	int a = 10;
    printf("a = %d\n",a);
    
    char c = 'A';
    printf("c = %c\n",c);
    
    float f = 1.2;
    printf("f = %f\n",f);
    
    double d = 3.14159;
    printf("d = %lf\n",d);
    
    char *str = "木易杨";
    puts(str);
    
    void (*p)(int data) = func;
    p(20);
    
    printf("========================\n");
    
    struct Datas d1;
    d1.a = 13;
    d1.c = 'b';
    d1.f = 6.5;
    d1.d = 5.3435;
    strcpy(d1.str,"弓长张");
    d1.p = func;
    
    printf("a = %d\n",d1.a);
    printf("c = %c\n",d1.c);
    printf("f = %f\n",d1.f);
    printf("d = %lf\n",d1.d);
    puts(d1.str);
    d1.p(40);
    
    system("pause");
    return 0;
}

执行结果:

a = 10
c = A
f = 1.200000
d = 3.141590
木易杨
函数:data = 20
========================
a = 13
c = b
f = 6.500000
d = 5.343500
弓长张
函数:data = 40

结构体使用注意

要注意结构体内的指针开辟空间问题

#include <stdio.h>
#include <stdlib.h>

struct Datas
{
	char *p;
};

struct Test
{
	char p[128];
};

int main()
{
    struct Test a;
    strcpy(a.p,"木易杨");
    puts(a.p);
    
    struct Datas b;
    b.p = (char *)malloc(128);
    memset(b.p, '\0', 128);
    strcpy(b.p,"弓长张");
    puts(b.p);
    
    system("pause");
    return 0;
}

执行结果:

木易杨
弓长张

学生成绩用结构体案例

struct Student stus[3];

结构体数组

#include <stdio.h>
#include <stdlib.h>

struct Student
{
	char *name;
    int score;
};

int main()
{
	int i;
    struct Student stus[3];
    
    for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++){
		printf("请输入第%d个学生的名字:\n",i+1);
        stus[i].name = (char *)malloc(20);
        memset(stus[i].name, '\0', 20);
        scanf("%s",stus[i].name);
        printf("请输入第%d个学生的分数:\n",i+1);
        scanf("%d",&stus[i].score);
    }
    
    for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++){
		printf("第%d个学生的成绩:\n",i+1);
        printf("%s:%d\n",stus[i].name,stus[i].score);
    }
    struct Student maxStu;
    maxStu = stus[0];
    struct Student minStu;
    minStu = stus[0];
    for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++){
		if(maxStu.score < stus[i].score){
			maxStu = stus[i];
        }else if(minStu.score > stus[i].score){
			minStu = stus[i];
        }
    }
    printf("最高分是%s分数为%d\n",maxStu.name,maxStu.score);
    
    printf("最低分是%s分数为%d\n",minStu.name,minStu.score);
    
    system("pause");
    return 0;
}

结构体指针应用

struct Student *p;

结构体指针

1、如果用结构体指针,访问就不能用!!!点运算符!!!访问结构体中的变量
要用->

2、指针要注意是否是野指针或者NULL

#include <stdio.h>
#include <stdlib.h>

struct Student
{
	char name[128];
    int score;
};

int main()
{
	int i;
    struct Student stu1;
    strcpy(stu1.name,"木易杨");
    stu1.score = 100;
    printf("名字:%s\n分数:%d\n",stu1.name,stu1.score);
    
    struct Student *p = NULL; //野指针
    //如果用结构体指针,访问就不能用点运算符访问结构体中的变量,要用->
    //指针要注意是否是野指针或者NULL
    p = (struct Student *)malloc(sizeof(struct Student));
    memset(p,'\0',sizeof(struct Student));
    p->score = 20;  
	strcpy(p->name,"弓长张");
    printf("名字:%s\n分数:%d\n",p->name,p->score);
    free(p);//释放掉开辟的空间
    p = &stu1;
    //把结构体变量的地址给到指针
    //指针是存放地址的变量,前面是指向malloc开辟的空间,现在是指针变量存放的在stu1的地址
	printf("名字:%s\n分数:%d\n",p->name,p->score);
    
    printf("p的地址是:%p\n",p++);
    printf("p++后的地址是:%p\n",p);
    
    system("pause");
    return 0;
}

执行结果:

名字:木易杨
分数:100
名字:弓长张
分数:20
名字:木易杨
分数:100
p的地址是:0060FE78
p++后的地址是:0060FEFC

结构体的一个偏移量是跨过整个结构体

struct Student
{
	char name[128];
    int score;
};

name = 128
score = 4

DEC:0060FEFC - 0060FE78 = 132

结构体数组跟结构体指针统合应用

p = stus;

把结构体数组的首地址给到指针

(*p).name;

取结构体指针内容,在选结构体内的元素

学生成绩录入案例:

#include <stdio.h>
#include <stdlib.h>

struct Student
{
	char *name;
    int score;
};

int main()
{
	int i;
    struct Student stus[3];
    
    struct Student *p = stus;
    for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++){
		printf("请输入姓名:\n");
        p->name = (char *)malloc(20);
        memset(p->name,'\0',20);
        scanf("%s",(*p).name);
        printf("请输入分数:\n");
        scanf("%d",&(p->score));
        p++;
    }
    p = stus;
    for(i=0;i<sizeof(stus)/sizeof(stus[0]);i++){
		printf("名字:%s,分数:%d\n",p->name,p->score);
        p++;
    }
    
    system("pause");
    return 0;
}

学生成绩录入全结构体指针操作

#include <stdio.h>
#include <stdlib.h>

struct Student
{
	char *name;
    int score;
};

int main()
{
	int i;
    int len = 0;
    printf("选择要录入的人数:\n");
    scanf("%d",&len);
    
    struct Student *p = (struct Student *)malloc(len*sizeof(struct Student));
    for(i=0;i<len;i++){
		printf("请输入姓名:\n");
        p->name = (char *)malloc(20);
        memset(p->name,'\0',20);
        scanf("%s",(*p).name);
        printf("请输入分数:\n");
        scanf("%d",&(p->score));
        p++;
    }
    p = p - len;
    for(i=0;i<len;i++){
		printf("名字:%s,分数:%d\n",p->name,p->score);
        p++;
    }
    
    system("pause");
    return 0;
}

结构体指针结合函数应用

#include <stdio.h>
#include <stdlib.h>

struct Student
{
	char *name;
    int score;
};

int initNumber(int len)
{
    printf("选择要录入的人数:\n");
    scanf("%d",&len);
    return len;
}

struct Student* initStuScore(struct Student *p,int len)
{
	int i;
    p = (struct Student *)malloc(len*sizeof(struct Student));
    for(i=0;i<len;i++){
		printf("请输入姓名:\n");
        p->name = (char *)malloc(20);
        memset(p->name,'\0',20);
        scanf("%s",(*p).name);
        printf("请输入分数:\n");
        scanf("%d",&(p->score));
        p++;
    }
    return p - len;
}

void printMes(struct Student *p,int len)
{
	int i;
    for(i=0;i<len;i++){
		printf("名字:%s,分数:%d\n",p->name,p->score);
        p++;
    }
}

struct Student* findMaxStu(struct Student *p,int len)
{
	int i;
    struct Student *maxStu;
    maxStu = p;
    for(i=0;i<len;i++){
		if(maxStu->score < p->score){
			maxStu = p;
        }
        p++;
    }
    return maxStu;
}

struct Student* findMinStu(struct Student *p,int len)
{
	int i;
    struct Student *minStu;
    minStu = p;
    for(i=0;i<len;i++){
		if(minStu->score > p->score){
			minStu = p;
        }
        p++;
    }
    return minStu;
}

float getAverage(struct Student *stus,int len)
{
	int i;
    float average;
    for(i=0;i<len;i++){
		average += stus->score;
        stus++;
    }
    return (float)average/len;
}

int main()
{
	int i;
    int len = 0;
    struct Student *stu = NULL;
    struct Student *max = NULL;
    struct Student *min = NULL;
    float average;
    
	len = initNumber(len);
    
    stu = initStuScore(stu,len);
    
    printMes(stu,len);
    
    max = findMaxStu(stu,len);
    
    min = findMinStu(stu,len);
    
    average = getAverage(stu,len);
    
    printf("%s最高分:%d\n%s最低分:%d\n平均分:%f\n",max->name,max->score,min->name,min->score,average);
    
    system("pause");
    return 0;
}

字符串对比:

int findForName(struct Student *p,int len,char *name)
{
	int i;
    for(i=0;i<len;i++){
		if(strcmp(name,p->name) == 0){
			return 1;
        }
        p++;
    }
    return -1;
}
    if(findForName(stu,len,"wang") == -1){
		printf("查无此人\n");
    }else if(findForName(stu,len,"wang") == 1){
		printf("找到了\n");
    }

结构体对齐计算方式2

1、结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
2、结构体大小必须是所有成员大小(不考虑数组,结构体内部的结构体)的整数倍
3、对齐方式会很浪费空间,但按照计算机的访问规则,这种对齐方式提升了效率

#pragma pack(4)

  • 指定向4对齐,最大是8
  • 指定一般只能写一个,多个就按第一个来
  • 成员小于限制,则按最大的来,成员大于限制则按限制来对齐
struct s6
{
	char ch;
    int i;
    float f;  
    double d;  //20--24
};
#include <stdio.h>
#include <stdlib.h>

struct s1
{
	char ch1;  //1
    char ch2;  //2 + 2 = 4  多空出了2个,来与下面的4个对齐
    int i;     //4 + 4 = 8  遵循结构体运算法则,偏移量必须是当前成员大小的整数倍,逻辑偏移了2,实际对照其规则是偏移了4
};

struct s2
{
	char ch1;  //1 + 3 = 4
    int i;     //4 + 4 = 8
    char ch2;  //8 + 1 + 3 = 12
};

struct s3
{
	char ch;  //1 + 3 = 4
    int i;     //4 + 4 + 2 = 10
    char str[10];  //10 + 10 = 20
    //结构体大小必须是所有成员大小(不考虑数组)的整数倍
};

struct s4
{
	char ch;  //1 + 3 = 4
    int i;    //4
    struct s{
		char ch1;
        int j;
    };
    float f;   //8 + 4 = 12
};

struct s5
{
	char ch;
    int i;
    union{
		char ch1;
        int j;
    };
    //联合体就只取里面最大的一个成员的大小
};

//#pragma pack(4)
//限制一般只能写一个,多个就按第一个来
//指定向4对齐,最大是8
//成员小于限制,则按最大的来,成员大于限制则按限制来对齐

struct s6
{
	char ch;
    int i;
    float f;  
    double d;  //20--24
//* ***  4
//****    4
//****     4
//********  8    20

//* *** **** 
//**** ****
//********    24
};

#pragma pack(10)

struct s7
{
	char ch;  //1 + 3
    int i;    //8
    float f;   //12
    double d;  //20
};

int main()
{
	printf("计算变量大小\n");
	printf("char:%d\n",sizeof(char));
    printf("int:%d\n",sizeof(int));
    printf("float:%d\n",sizeof(float));
    printf("double:%d\n",sizeof(double));
    printf("计算结构体变量大小\n");
	printf("s1:%d\n",sizeof(struct s1));
    printf("s2:%d\n",sizeof(struct s2));
    printf("s3:%d\n",sizeof(struct s3));
    printf("s4:%d\n",sizeof(struct s4));
    printf("s5:%d\n",sizeof(struct s5));
    printf("s6:%d\n",sizeof(struct s6));
    printf("s7:%d\n",sizeof(struct s7));
    
    system("pause");
    return 0;
}

执行结果:

计算变量大小
char:1
int:4
float:4
double:8
计算结构体变量大小
s1:8
s2:12
s3:20
s4:12
s5:12
s6:24
s7:24

typedef关键字

typedef
typedef 为C语言的关键字
作用是为一种数据类型定义一个新名字
这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)

和struct来匹配,为了代码编写的简洁
和普通类型匹配,通过名字来获取一些信息

#include <stdio.h>
#include <stdlib.h>	

typedef unsigned char u_int8;  //(0 255)
typedef unsigned short int u_int16;
typedef unsigned int u_int32;

typedef struct Student
{
	char *name;
    int score;
    void (*p)(struct Student stu);
}STU,*PSTU;


typedef struct
{
	char *name;
    int score;
}STUS,*PSTUS;

typedef struct Node
{
	int data;
    struct Node* next;
}NODE,*PNODE;

int main()
{
	u_int8 data = 10;
    u_int16 data2 = 20;
    u_int32 data3 = 40;
    unsigned short int data4 = 70;
    
    printf("%d, %d, %d, %d\n",data,data2,data3,data4);
    
    struct Student stu1;
    stu1.score = 100;
    printf("stu1:score = %d\n",stu1.score);
    
    STU stu2;
    stu2.score = 50;
    printf("stu2:score = %d\n",stu2.score);
    
    struct Student *pstus;
    pstus = (struct Student *)malloc(sizeof(struct Student));
    pstus->score = 79;
    printf("pstu:score = %d\n",pstus->score);
    
    PSTU pstu;
    pstu = (PSTU)malloc(sizeof(STU));
    pstu->score = 99;
    printf("pstu:score = %d\n",pstu->score);
    
    system("pause");
    return 0;
}

  1. 结构体参考 ??

  2. 结构体对齐计算参考 ??

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-12 12:59:34  更:2021-09-12 12:59:37 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 13:56:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计