C 语言数据类型分为四大类:基本数据类型(short、int、long 、char、float、double)、指针类型、构造数据类型(结构体、共用体、枚举 )、空类型 void
(一)结构体
1.声明结构体
struct 名称
{
数据类型 成员1;
数据类型 成员2;
数据类型 成员3;
};
示例:声明“struct 名称”的结构体类型,是一种数据类型
struct date
{
int year;
int mon;
int day;
};
struct time
{
int hour;
int min;
int sec;
};
struct datetime
{
int year;
int mon;
int day;
int hour;
int min;
int sec;
};
struct datetime
{
struct date mdate;
struct time mtm;
};
struct datetime
{
struct date
{
int year;
int mon;
int day;
}mdate;
struct time
{
int hour;
int min;
int sec;
}mtm;
};
struct
{
int year;
int mon;
int day;
};
注意:1)声明结构体的时候,结构体{}后面的“;”不能省略
2)结构体成员之间用“;”隔开
3)struct后面的“名称”可以省略,省略后就是一个匿名结构体
2.定义结构体变量
int num;
结构体类型 变量名;
struct date mydate;
struct
{
int year;
int mon;
int day;
}mydate;
声明结构体类型的同时,定义了一个变量,变量的变量名mydate;
3.初始化结构体
(1)全部初始化:
struct date mydate = {2007, 7, 7};
struct datetime
{
struct date mdate;
struct time mtm;
};
struct datetime mydt = {{2007, 7, 7}, {14, 5, 23}};
(2)部分初始化:
struct date mydate =
{
.year = 2024,
.day = 6,
};
4.访问结构体数据成员
(1)通过结构体变量访问结构体成员
结构变量变量名.成员1;
结构变量变量名.成员2;
结构变量变量名.成员3;
结构变量变量名.成员1; //表达式的结果取决成员的数据类型
mydate.year;
mydate.mon;
mydate.day;
(2)通过结构体指针访问结构体成员
结构体指针->成员1;
结构体指针->成员2;
结构体指针->成员3;
结构变量变量名.成员1; //表达式的结果取决成员的数据类型
5.结构体的存储方式
(1)结构体对齐原则
- 结构体成员在内存中存储时,成员必须存储在自己字节大小的整数倍位置
- 结构体整体占的内存大小,是结构体中最大成员字节数的整数倍
(2)注意
- 在不同位系统下,相同结构体在内存中占的字节空间可能不一样
原因:64位系统long/指针类型占8字节;32位系统long/指针类型占4字节。
- 可以强制让结构体按指定字节数对齐
#pragma pack(1) //强制结构体按1字节对齐
struct s
{
int a; //4
char b; //1
int c; //4
};
#pragma pack() //取消强制结构体按1字节对齐
sizeof(s) —>9字节
示例:
//12字节
struct s1
{
short a;
int b;
char c;
};
//8字节
struct s2
{
char a; //2 (0->1)
short b; //2 (2->3)
int c; //4 (4->7)
};
//64bit –> 24 //32bit–>16
struct s3
{
char a; //4 (0->3)
int b; //4 (4->7)
short c; //8 (8->15) //8->11
long d; //8 (16->23) //12->15
};
//64bit 16 32bit–>8
struct s4
{
char a;
int *p;
};
//24字节
struct s5
{
char a[16]; //0-15
char b; //16
int c; //20-23
};
6.结构体作为函数参数传递
-
如果要在被调函数中修改主调函数中的结构体变量,则传递结构体变量的地址
-
如果在被调函数中使用主调函数中定义的结构体变量,可以值传递,也可以传地址
7.结构体数组
struct 名称 数组名[元素个数];
struct 名称 数组名[元素个数] = {{}, {}, {}};
数组名[下标]; —》数据类型:”struct 名称“ 类型
结构体数组中的成员访问:
struct stu ss[4] = {
{"zhangsan", 23, 90}, {"lisi", 22, 67},
{"wanger", 24, 89}, {"zhaowu", 20, 99}};
void printf_stu_array(struct stu *ss, int len)
{
for (int i = 0; i < len; ++i)
{
//struct stu
printf("%s %d %d\\n", ss[i].name, ss[i].age, ss[i].score);
//struct stu *
printf("%s %d %d\\n", (ss+i)->name, (ss+i)->age, (ss+i)->score);
//struct stu
printf("%s %d %d\\n", (*(ss+i)).name, (*(ss+i)).age, (*(ss+i)).score);
}
}
(二)共用体
1.基本语法
声明共用体:
union 名称
{
数据类型 成员1;
数据类型 成员2;
数据类型 成员3;
};
定义共用体变量:
union 名称 变量名;
特点:
(1)共用体中的所有成员共用一块内存空间;
(2)共用体在内存中占的字节数取决于最大字节数的成员;
(3)共用体存储的数据,和最后一次的成员赋值有关。
2.内存大小段存储方式
- 小端:内存的高地址存储高字节位,内存的低地址存储低字节位
- 大端:内存的高地址存储低字节位,内存的低地址存储高字节位

大小端测试方式:
-
指针方式:
int main(void)
{
int a = 0x11223344;
char *p = (char *)&a;
if (*p == 0x44)
{
printf("small\\n");
}
else
{
printf("big\\n");
}
}
-
共用体方式:
union s
{
int a;
char b;
};
int main(void)
{
union s tmp;
tmp.a = 1;
if (tmp.b)
{
printf("small\\n");
}
else
{
printf("big\\n");
}
return 0;
}

(三)枚举
基本语法
枚举类型的声明:
enum 名称
{
枚举常量1,
枚举常量2,
枚举常量3,
};
#define RED 0
#define BLUE 1
符号常量
注意:
枚举里面的成员都是枚举常量,都是整形常量,所以不需要写数据类型;
枚举常量根据行业规范,一般写成大写方式,和普通变量区分;
枚举中的枚举常量,类似于整形符号常量,可以直接被引用;
枚举中的常量和常量之间用逗号隔开;
枚举中的枚举常量如果没有给定初始值,则默认从0开始;
如果给其中的某个枚举常量给定了初始值,则后面的常量以该值为基础自增1;
枚举变量
enum 名称 变量名;
枚举变量是枚举类型,但本质是一个整型
变量名 = 枚举常量;
(四)typedef关键字
typedef:为已有的数据类型重命名
typedef 已有的数据类型 新名字;
typedef enum week
{
MON = 1,
TUE,
WED,
THU,
FRI,
SAT,
SUN,
}WEEK_e;
typedef struct stu
{
char name[32];
int score;
}STU_s;
struct stu1
{
char name[32];
int score;
};
typedef struct stu1 STU1_s;
typedef union name
{
char a;
int b;
short c;
}NAME_u;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
typedef unsigned long u64;
typedef signed int s32;
网硕互联帮助中心




评论前必须登录!
注册