c || 结构体 联合体 枚举类型 字符串

结构体struct :类型设计

  1. 形参的改变不会改变实参
  2. 单独的定义会存在数组名的退化,但在结构体中的数组不存在数组名的退化
    3)调用对象的属性使用 对象名.属性
    调用指针的属性使用 指针->属性
   struct Student//类型设计
   {
        char s_id[10];
        char s_name[10];
        int s_age;
    }stud; //对象
    void InitStudent(struct Student *stud)  //初始化结构体  传入自己的地址
    {
    	printf("id  name age \n");
    	scanf_s("%s",stud->s_id);
    	scanf_s("%s",stud->s_name);    //数组名本身就表示地址
    	scanf_s("%d",&stud->s_id);     //整形 要传地址  否则形参不能改变实参
    }
        void PrintStudent(const struct Student *stud)  //输出结构体内容  不希望改变参数值
    {
    	assert(stud!=NULL);
    	printf("id  name age \n");
    	scanf_s("%s",stud->s_id);
    	scanf_s("%s",stud->s_name);    //数组名本身就表示地址
    	scanf_s("%d",stud->s_id);     //整形 要传地址  否则形参不能改变实参
    }
int main()
{
    struct Student x;            //x被称为对象,操纵结构体变量,用(.)进行使用
    struct Student x = {"09001","lili",18};  //按照顺序初始化,和结构体顺序要保持一致
    struct Student *p = &x;
    printf("%s \n",(*p).s_id);  //指针的属性输出
	printf("%s \n",p->s_id);
	
    struct Student y = x;       //可以进行初始化
    struct Student z = {};
    z = x;                      //可以进行赋值
    
    printf("%s \n",x.s_id);     //输出使用.运算符
    strcpy_s(x.s_id,10"09001");//引入#in clude<string.h>,vs2019不用strcpy,改为strcpy_s
    int a;//a被称为变量
    
	InitStudent(&studx);        //初始化studx 使用自己本身
	PrintStudent(&studx);
    return 0;
}
int main()     //字符串
{
	char s_id[20] = {"020303"}; //ok  初始化可以
	
	char s_id[20]; 
	s_id = {"292929"}     //err	 不能赋值  数组名退化为指针常量  不能进行赋值
	
	int ar[10];   数组定义:类型 大小
	sizeof(ar);   //sizeof(int)*10   40
}

形参改变不能改变实参的值

结构体赋值

  1. 定义结构体变量 { }初始化
  2. 用已定义的结构变量初始化
  3. 结构体类型相同的变量可以作为整体相互赋值 //赋值

结构体类型指针

  1. (*p).成员名
  2. p->成员名
#include<stdio.h>
#include<iostream>
using namespace std;
struct Student
{
	char s_name[8];  //8
	int s_age;//12
};
void Prinf(const struct Student* sp) //打印函数 不会改变 加上常属性
{
	cout << sp->s_age << " " << sp->s_name << endl;
}
int main()
{
	int n = sizeof(Student);
	cout << n<<endl;  //12
	struct Student sta = { "lee",21 };
	Student* stb = &sta;      //初始化
	char name[20] = { 0 };

	(*stb).s_age = 18; 
	stb->s_age = 18;

	strcpy_s(name, stb->s_name);
	printf("%d\n", stb->s_age);
	cout << (*stb).s_name << endl;
	Prinf(stb);
	return 0;
}

结构体的内存对齐

  1. 结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍
  2. 结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节数的整数倍
  3. 结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节数”的整数倍

基本数据类型字节数

字节数注意:
CPU不是以逐字节读写内存,而是以2,4,8的倍数的字节块来读写内存,因此基本数据类型的地址必须是2,4,8的倍数,那就要求各种数据类型按照一定的规则在空间上排列,这就是对齐

struct node
{
	char cha;    //1  偏移7个字节   8
	double da;   //16  
	char chb;    //1  偏移7个字节   24
};   //sizeof(struct node) = 24

struct node
{
	char ch[3]; //3 偏移1个字节
	int ia;     //8
};     //sizeof(struct node) = 8

struct sdate   //12
{
	int year;
	int month;
	int day;
};
struct Student
{
	char s_id[10]; //10
	char s_name[8];//18
	struct sdate birthday; //12+18  30   基本数据类型 int
	double grade; //30+8  38 偏移2  到40 最大数据类型
}; //sizeof(Student) = 40

指定对齐值

预处理指令 #pragma pack(n) 可以改变默认对齐数 n = 1,2,4,8,16
需要以**#pragma pack()结束**,表示该种对齐方式到此为止
VS中默认值 = 8; gcc默认值 = 4

#pragma pack(4)
struct node
{
	char cha;   //1
	int ia;     //8
	short sa;   //12
}; //sizeof(node) = 12
#pragma pack()

#pragma pack(1)
struct node
{
	char cha;   //1
	int ia;     //1+4 = 5
	short sa;   //5+2 = 7
}; //sizeof(node) = 7
#pragma pack()

#pragma pack(8)
struct anode
{
	short sa;   //2 
	long int ib; //8
};//8
struct bnode
{
	char ca; //1 8
	struct anode ad; //8+8 16
	double dx; //24
}; //24
#pragma pack()

例题
在这里插入图片描述

struct Student
{
	char s_name[20];
	int age;
	int score;
};
int Sumscore(struct Student* sp,int n)       //总成绩
{
	int sum = 0;
	for(int i = 0; i < n; i++)
	{
		sum += sp[i].score;
	}
	return sum;
}
int Ave(struct Student* p, int n)           //平均成绩
{
	int sum = Sumscore(p, n);
	int ave = sum / n;
	return ave;
}
void SortByScore(struct Student* p, int n) //按成绩排序
{
	for (int i = 0; i < n; i++)
	{
		if (p[i].score > p[i + 1].score)
		{
			swap(p[i].score, p[i + 1].score);
		}
	}
}
void Printf(struct Student* p, int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << p[i].s_name << " " << p[i].age << " " << p[i].score << endl;
	}
}
int main()
{
	struct Student cla[ ] =
	{
		{"lee",18,40},
		{"lolo",40,23},
		{"rere",34,23},
	};
	int k = sizeof(cla) / sizeof(cla[0]);
	int sum = Sumscore(cla, k);
	cout << sum << endl;

	int ave = Ave(cla, k);
	cout << ave << endl;

	SortByScore(cla, k);
	Printf(cla, k);
	return 0;
}

联合体union

1.结构体各成员有各自的内存空间,在联合体中,各成员共享同一段内存空间
2.一个联合体变量的长度等于各成员中最长的长度
3.一个联合体类型必须经过定义之后,才能使用它,才能把一个变量声明定义为联合体类型

共享指的是联合体变量可被赋予任一成员值,但每次只能赋一种值,赋入新值则冲去旧值。

union Data
{
	short st;
	char cs[2];
}x;

枚举:把需要的取值一一列举

特点:
1)受到限制的有符号整形类型;
2)枚举值必须是整型类型
3)枚举变量的取值范围必须是枚举值集合
4)枚举变量的取值只能赋值为{枚举值集合中值};
5)枚举变量不能++,–

//不指定值,默认从0开始 往后逐个加一
enum week{mon,tue,wend,thurs,fri,sat,sun}; 
//指定值
enum week{mon = 1,tues = 2,wed = 3,thurs = 4};
//只给第一个名字指定值 往后逐个加一
enum week{mon = 1,thes,wed,thurs,fri,sat,sun};
enum week x = Mon;

枚举与#define的区别

1.增加代码的可读性和可维护性
2.枚举类型有类型检查,更严谨
3.封装性好
3.一次可以定义多个常量

//整型转换成枚举
int main(){
    enum day{saturday,sunday,monday,tuesday,wednesday,thursday,friday}workday;
    int a=1;
    enum day weekend;
    weekend=(enum day)a;
    printf("weekend:%d",weekend);
    return 0;
}

字符串

  • print输出格式
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值