c语言结构体---详解(零基础~)

本文详细介绍了C语言中的结构体概念,包括如何定义、初始化结构体,结构体成员的访问方式,结构体与指针、函数的关系,以及结构体数组和柔性数组的使用及其优势。
摘要由CSDN通过智能技术生成

每日励志:

有的人,一辈子只做两件事,不服,争取,所以越来越好。也有人,一辈子只做两件事,等待,后悔,所以越混越差。

一、结构体的设计

C语言提供了基本的数据结构,例如 char 、short 、int 、float....等类型;这些偶称为内置类型。怎样设计出来属于自己的类型?

程序员可以使用结构体来封装一些属性,设计出新的类型,在C语言中称为结构体类型。

结构体的定义形式为

struct 结构体名
{
   成员列表(可以是基本的数据类型,指针,数组或其他结构类型)
};

客观事务(实体)是复杂的,要描述它必须从多方面进行;也就是用不同的数据类型来描述不同的方面;用学生实体来说:

学生拥有什么? 学号、姓名、性别、年龄;

struct Student
{
  char s_id[8];  //学号
  char s_name[8];  //姓名
  char s_sex[4];   //性别
  int s_age;      //年龄
};

注意以下几点;

(1)、关键字struct是数据类型说明符,指出下面说的是结构体类型;

(2)、标识符Student是结构体的类型名;

(3)、最后的分号一定要写;

二、结构体变量的初始化

结构体是一种数据类型,也就是说可以用它来定义变量。

结构体就像一个“模板”,定义出来的变量都具有相同的性质。可以将结构体比作“图纸”,结构体变量比作“零件”,根据同一张图纸生产出来的零件的特性都是一样的;

结构体是一种数据类型,是创建变量的模板,不占用内存空间;结构体变量才包含了实实在在的数据、需要存储空间;


//结构体变量的定义和初始化
#include <stdio.h>

struct stu {
	char name[20];
	char sex[10];
	int age;
} s4, s5; //结构体变量也是----全局变量

struct stu s6;//全局变量

//使用指针打印结构体
void print(struct stu *s) {
	printf("%s %s %d", (*s).name, (*s).sex, (*s).age);
}

int main() {
	struct stu  s2, s3; //结构体变量也是局部变量
	struct stu	s1 = {"aa", "a", 10}; //结构体初始化
//	scanf("%s %s %d", s2.name, s2.sex, s2.age); //结构体初始化
//s3={"kk","k",1};   注意不可以这样写
	//打印结构体
	//结构成员访问
	printf("%s %s %d\n", s1.name, s1.sex, s1.age);
	print(&s1); //调用函数打印
	return 0;
}
 2.1结构体嵌套结构体
 
//结构体嵌套

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

struct date {
	int year;
	int month;
	int day;
};

struct stu {
	char name[20];
	struct date birthday;
	int age;


};


int main() {
	struct stu s1 = {"张三", 2000, 10, 1, 11}; //这里加f是因为是float类型,f代表float
	printf("%s %d %d %d %d", s1.name, s1.birthday.year, s1.birthday.month, s1.birthday.day, s1.age);

	return 0;
}

三、结构体成员访问 

3.1、结构体成员访问

结构体变量使用   .   访问;

结构体变量.对象

	printf("%s %s %d\n", s1.name, s1.sex, s1.age);

注意:对结构体变量整体赋值有三种情况

 (1)定义结构体变量(用{}初始化)

(2)用已定义的结构体变量初始化

(3)结构体类型相同的变量可以作为整体相互赋值;

在C语言中不存在结构体类型的强制转换。

3.2、结构体变量和指针

内置类型可以定义指针变量,结构体类型也可以定义结构体类型指针;

结构体类型指针访问成员的获取和赋值形式:

(1)(*p). 成员名(.的优先级高于*,(*p)两边括号不能少)

(2)   p->成员名(->指向符)

示例:

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

//#define _CRT_SECURE_NO_WARNINGS
struct Inventory { //商品
	char description[20];//货物名
	int quantity;//库存数据
};

int main() {
	struct Inventory sta = { "iphone", 20 };
	struct Inventory *stp = &sta;
	char name[20] = { 0 };
	int num = 0;
	(*stp).quantity = 30;
	stp->quantity = 30;
	strcpy_s(name, sizeof(stp->description), stp->description);
	printf("%s %d\n", stp->description, stp->quantity);
	printf("%s %d\n", (*stp).description, (*stp).quantity);
	return 0;
}

 3.3、结构体和函数 

示例:

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

struct School {
	char s_name[20];//学校
	int s_age;
};

void Print_a(struct School sx) {
	printf("%s %d\n", sx.s_name, sx.s_age);
}

void Print_c(struct School *sp) {
	printf("%s %d\n", sp->s_name, sp->s_age);
}

int main() {
	struct School sx = { "xi'an", 100 };
	Print_a(sx);
	Print_c(&sx);
	return 0;
}

四、结构体与数组

结构体数组,是指数组中的每一个元素都是一个结构体类型。在实际应用中,C语言结构体数组常被用来表示有相同的数据结构的群体,比如一个班的学生,一个公司的员工等;

例如:

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

struct Student {
	char s_name[20];//姓名
	int age;//年龄
	float score;//成绩
};

int main() {
	struct Student cla[] = {
		{"liuwen", 18, 149.9},
		{"qnge", 18, 145},
		{"anan", 19, 188},
	};
	return 0;
}

五、计算结构体大小  (注:?)

三个规则:

1)、结构体变量的首地址,必须是结构体变量的“最大基本数据类型成员所占字节数”的整数倍;

(2)结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍;

(3)、结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节”的整数倍;

示例:假设总零地址开始(计算)

例1、

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

struct node {
	char cha;
	int ia;
	char chb;
};

int main() {
	int size = 0;
	struct node sd = { 'a', 2, 'b' };
	printf("%d\n", sizeof(struct node));//12
	return 0;
}

六、计算结构体大小  (注:?)

一.定义:

也许你从来没有听说过 柔性数组( flexible array  这个概念,但是它确实是存在的。

C99 中, 结构中的最后一个元素允许是未知大小的数组 ,这就叫做 『柔性数组』 成员。

typedef struct st_type
{
 int i;
 int a[0];//柔性数组成员
}type_a;
typedef struct st_type
{
 int i;
 int a[];//柔性数组成员
}type_a;
二.柔性数组的特点 

1.结构中的柔性数组成员 前面必须至少一个其他成员 。
2. sizeof 返回的这种结构大小不包括柔性数组的内存。
3.包含柔性数组成员的结构用 malloc () 函数进行内存的动态分配,并且分配的内存应该大于结构的大 小,以适应柔性数组的预期大小。

#include<stdio.h>
#include<stdlib.h>
typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;
int main()
{
	printf("%d\n", sizeof(type_a));//输出的是4
}

三.柔性数组的使用
#include<stdio.h>
#include<stdlib.h>
struct pep
{
	int n;
	int a[];
};
int main()
{
	struct pep* ps=(struct peo*)malloc(sizeof(struct pep)+40);
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 10;
	
	for (int i = 0; i < 10; i++)
	{
		
		ps->a[i] = i;
	}
	for (int i = 0; i < 10; i++)
	{
 
		printf("%d",(ps->a[i]));
		printf("\n");
	}
	free(ps);
	return 0;
}
四.柔性数组的优势

我们可以让两个代码进行比较

代码1:

#include<stdio.h>
#include<stdlib.h>
struct pep
{
	int n;
	int a[];
};
int main()
{
	struct pep* ps=(struct peo*)malloc(sizeof(struct pep)+40);
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 10;
	
	for (int i = 0; i < 10; i++)
	{
		
		ps->a[i] = i;
	}
	for (int i = 0; i < 10; i++)
	{
 
		printf("%d",(ps->a[i]));
		printf("\n");
	}
	free(ps);
	return 0;
}
#include<stdio.h>
#include<stdlib.h>
struct pep
{
	int n;
	int *a;
};
int main()
{
	struct pep* ps = (struct pep*)malloc(sizeof(struct pep) + 40);
	if (ps == NULL)
	{
		return 1;
	}
	ps->n = 10;
	ps->a = (int*)malloc(40);
	if (ps->a == NULL)
	{
		return 1;
	}
	for (int i = 0; i < 10; i++)
	{
 
		ps->a[i] = i;
	}
	for (int i = 0; i < 10; i++)
	{
 
		printf("%d", (ps->a[i]));
		printf("\n");
	}
	free(ps->a);
	free(ps);
	ps = NULL;
	return 0;
}

第一个好处是: 方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给
用户。用户调用 free 可以释放结构体,但是用户并不知道这个结构体内的成员也需要 free ,所以你
不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好
了,并返回给用户一个结构体指针,用户做一次 free 就可以把所有的内存也给释放掉。
 

第二个好处是: 这样有利于访问速度.

连续的内存有益于提高访问速度,也有益于减少 内 存 碎 片。(其实,我个人觉得也没多高了,反正

你跑不了要用做偏移量的加法来寻址)

c语言结构体练习题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值