结构体类型和结构体变量, struct
定义结构体类型时 不占内存
匿名结构体,无法创建变量访问,有限的结构体类型变量
结构体变量不能整体引用,只能引用变量成员
结构体变量用大括号赋值,只有在创建并初始化的时候才可以
同一类型的结构体变量之间可以直接互相赋值,结构体类型定义的时候,不可以赋初值
字符串不能直接赋值
结构体内部再定义一个结构体,没有创建结构体的实例,
再次定义的结构体内部的变量,会被当作母结构体的成员变量
结构体内部再定义一个结构体,创建结构体变量,该变量会直接作为一个成员
结构体数组在内存中是连续排列的
结构体 共用体 所占内存大小一定大于等于所有的成员的字节之和,准则3:
1、结构体变量大小能够被最宽基本类型成员的大小所整除
2、结构体每个成员相对于结构体首地址的偏移量都是成员的大小的整数倍,如有需要编译器会在成员之间填充字节
3、结构体的总大小为结构体最宽基本类型大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节
内存大小和成员的位置顺序有也关系
结构体可以嵌套共用体,也可以在内部定义共用体
共用体 union
共用体变量任何时刻只有一个成员存在,共用体变量在分配内存时,长度等于最长成员所占的字节
共用体大小必须包含最大的成员数据,可以整除最小的成员数据,内存对齐机制
共用体大括号初始化的时候只能初始化第一个成员,共用体变量可以直接赋值
共用体和结构体的差别,在于内存的机制不同,共用体任何时刻只有一个成员,结构体所有成员均存在,共用体用大括号初始化的时候只能对第一个成语初始化
用法和结构体类似
枚举类型 enum
列举了所有的情况,用枚举类型声明变量时,只能取集合中的某项作为值,一定程度保证了取值的安全性
类型取别名 typedef 方便程序的移植
typedef unsigned int uint
typedef 没有创建数据类型,给已经有的数据类型起别名仅仅适用于类型,编译的时候处理
类型定义可以嵌套
typedef 步骤:
1、按照定义变量的方式写出定义体 如 int i;
2、将变量名换成新类型名 如 int INTEFER;
3、最前面加typedef 如 typedef int INTEGER;
4、用新类型名定义变量 如 INTEGER i,j;
#define uint unsigned int 适用任何场合,预处理
深拷贝 复制内存地址的内容
浅拷贝 共享内存地址
字节对齐规则
定义结构体类型时 不占内存
匿名结构体,无法创建变量访问,有限的结构体类型变量
结构体变量不能整体引用,只能引用变量成员
结构体变量用大括号赋值,只有在创建并初始化的时候才可以
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//结构体变量定义形式一
struct nameinfo //声明结构体类型,,不分配内存
{
char name[50];
char phone[50];
int num;
int nameinfo; //成员名和类型名可以重名
};
//struct nameinfo zqh; //声明结构体变量
//结构体变量定义形式二
//#define info struct nameinfo
//info //声明结构体类型
//{
// char name[50];
// char phone[50];
// int num;
//};
//info zqh; //声明结构体变量
//结构体变量定义形式三
//struct nameinfo //声明结构体类型
//{
// char name[50];
// char phone[50];
// int num;
//} zqh; //声明结构体变量
int main()
{
struct nameinfo zqh = {"梵高先生","1506051****",2018}; //声明结构体变量
//结构体变量用大括号赋值,
//只有在创建并初始化的时候才可以
//zqh.num = 2018;
//strcpy(zqh.name,"梵高先生"); //字符串不可以赋值号赋值
//sprintf(zqh.phone,"1506051****"); //字符串变量赋值的两种方式
printf("%d %s %s\n", zqh.num, zqh.name, zqh.phone);
//struct nameinfo qh = zqh; //同一类型的结构体变量之间可以直接互相赋值
//printf("%d %s %s\n", qh.num, qh.name, qh.phone);
system("pause");
}
同一类型的结构体变量之间可以直接互相赋值,结构体类型定义的时候,不可以赋初值
字符串不能直接赋值
结构体内部再定义一个结构体,没有创建结构体的实例,
再次定义的结构体内部的变量,会被当作母结构体的成员变量
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct YouStruct
{
char phone[15];
char addr[15];
};
struct MyStruct
{
int year;
char name[20];
struct YouStruct you; //结构体嵌套
};
int main()
{
struct MyStruct num[10]; //定义结构体数组,同定义结构体变量3种形式
struct MyStruct zqh;
//初始化方式1
strcpy(zqh.name, "梵高先生");
zqh.year = 22;
strcpy(zqh.you.addr , "平和县"); //结构体嵌套访问
sprintf(zqh.you.phone, "1506051****");
printf("%s %d %s %s\n",zqh.name,zqh.year,zqh.you.addr,zqh.you.phone);
//初始化方式2
struct MyStruct zzz =
{
22, "董卓瑶", { "15*********", "南京" }
};
printf("%s %d %s %s\n", zzz.name, zzz.year,zzz.you.addr, zzz.you.phone);
system("pause");
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
int main()
{
struct mystruct my; //定义结构体变量
my.num = 2351;
strcpy(my.uct, "梵高先生");
printf("my.uct=%d my.uct = %s\n",my.num,my.uct);
struct mystruct *p = &my; //定义结构体指针,并初始化
printf("%p\n",p);
//指针访问结构体方式一
(*p).num = 1990;
sprintf((*p).uct,"你好,明天");
printf("(*p).num=%d (*p).uct=%s\n", (*p).num, (*p).uct);
//指针访问结构体方式二
p->num = 3195;
strcpy(p->uct,"热河");
printf(" p->num=%d p->uct=%s\n", p->num, p->uct);
system("pause");
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
//结构体函数参数传递也有副本机制,使用结构体作为参数,很浪费内存,不能修改函数外部的数据
//用指针可以修改函数外部的数据
void changes(struct mystruct *p)
{
p->num = 200300;
}
int main()
{
struct mystruct my ; //定义结构体变量
struct mystruct *p; //指向结构体数组的指针
p = &my; //初始化指针
p->num = 100200;
strcpy(p->uct, "梵高先生");
printf("%d %s\n",p->num,p->uct);
changes(p);
printf("%d %s\n", p->num, p->uct);
system("pause");
}
结构体内部再定义一个结构体,创建结构体变量,该变量会直接作为一个成员
结构体数组在内存中是连续排列的
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
int main()
{
struct mystruct my[5] = //定义结构体数组
{
{100200,"梵高先生"},
{200300,"下雨"},
{300400,"山阴路的夏天"},
{400500,"关于郑州的记忆"},
{500600,"杭州"}
};
struct mystruct *p ; //指向结构体数组的指针
p = my; //初始化指针
for (struct mystruct *pa = p; pa < p+5; pa++)//指针遍历结构体数组
{
printf("%d %s\n",pa->num,pa->uct);
}
system("pause");
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct
{
int num;
char uct[20];
};
int main()
{
struct mystruct *p = (struct mystruct *)malloc(sizeof(struct mystruct)*5);
//分配内存
int num = 100200;
char str[5][20] = { "梵高先生", "下雨" , "山阴路的夏天" ,"关于郑州的记忆" , "杭州" };
char (*pstr)[20] = str;
//创建一个指针存储二维数组的首地址,一个指向有20个元素的一维数组的指针
for (struct mystruct * pa = p; pa < p + 5; pa++) //写数据
{
pa->num = num;
strcpy(pa->uct, pstr);
num += 100100;
pstr ++;
}
for (struct mystruct * pa = p; pa < p + 5; pa++) //读数据
printf("%d %s\n", pa->num, pa->uct);
free(p); //释放内存
system("pause");
}
结构体 共用体 所占内存大小一定大于等于所有的成员的字节之和,准则3:
1、结构体变量大小能够被最宽基本类型成员的大小所整除
2、结构体每个成员相对于结构体首地址的偏移量都是成员的大小的整数倍,如有需要编译器会在成员之间填充字节
3、结构体的总大小为结构体最宽基本类型大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节
内存大小和成员的位置顺序有也关系
结构体可以嵌套共用体,也可以在内部定义共用体
共用体 union
共用体变量任何时刻只有一个成员存在,共用体变量在分配内存时,长度等于最长成员所占的字节
共用体大小必须包含最大的成员数据,可以整除最小的成员数据,内存对齐机制
共用体大括号初始化的时候只能初始化第一个成员,共用体变量可以直接赋值
共用体和结构体的差别,在于内存的机制不同,共用体任何时刻只有一个成员,结构体所有成员均存在,共用体用大括号初始化的时候只能对第一个成语初始化
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//任意时刻只有一个成员存在
//共用体大小必须包含最大的成员数据,可以整除最小的成员数据,内存机制
union info //共用体和结构体类似,
{
int u32;
float f32;
char str[9];
};
int main()
{
union info num;
union info *p = #
union info num1 = num; //共用体可以直接赋值
//共用体大括号初始化的时候只能初始化第一个成员
num.u32 = 15;
num.f32 = 12.7;
strcpy(num.str, "梵高先生");
printf("%d %f %s\n",num.u32,num.f32,num.str);
//最后的结果取决于最后的赋值
printf("%d %f %s\n", p->u32,p->f32, p->str);
//以指针的方式引用
printf("所占字节%d\n", sizeof(num));
system("pause");
}
用法和结构体类似
枚举类型 enum
列举了所有的情况,用枚举类型声明变量时,只能取集合中的某项作为值,一定程度保证了取值的安全性
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
enum level //定义枚举类型
{
T1 = 8,T2,T3,T4 = 8,T5,T6,T7,T8,T9,T10
};
int main()
{
//枚举型变量,可以将数据限定在一定范围之内
//刨除多余数据
enum level num = T8; //声明枚举类型变量
printf("%d\n",T1); //如果没有指定初值的值默认编号从0开始依次增大
printf("%d\n", T2);
printf("%d\n", T3);
printf("%d\n", T4);
printf("%d\n", T5);
system("pause");
}
类型取别名 typedef 方便程序的移植
typedef unsigned int uint
typedef 没有创建数据类型,给已经有的数据类型起别名仅仅适用于类型,编译的时候处理
类型定义可以嵌套
typedef 步骤:
1、按照定义变量的方式写出定义体 如 int i;
2、将变量名换成新类型名 如 int INTEFER;
3、最前面加typedef 如 typedef int INTEGER;
4、用新类型名定义变量 如 INTEGER i,j;
#define uint unsigned int 适用任何场合,预处理
深拷贝 复制内存地址的内容
浅拷贝 共享内存地址
字节对齐规则