1.结构体内存对齐
(1)在设计结构体时,既要满足对齐,又要节省空间(让占用空间小的成员尽量集中在一起)
struct s1
{ char c1;
char c2;
int i;//占用8个字节
struct s2
{ char c1;
int i;
char c2;//占用12个字节
(2)修改默认对齐数
#pragma pack(4) //设置为4
#pragma pack() //取消设置的默认对齐数
(3)写一个宏,计算结构体中某变量相对于首地址的偏移(百度笔试题)//offsetof宏
头文件#include
printf("%d",offsetof(struct name,struct member name));
(4)位段,为了节省空间。但是不能跨平台
struct S
{
int a:2;//是占据int型(4个字节*8=32bits中的2个比特位)
int b:5;
int c:15;
int d:30; //sizeof(S)=8个字节,a,b,c占据4个字节中的22个bit
int main()
{
s.a=10;
s.b=20;//是把数字先转化为二进制再存储
}
2.枚举(当需要define多个变量时,用枚举来代替)
#include
enum Color
{
RED,//0
GREEN,//1
BLUE //2 枚举的可能取值——常量,main里面不能修改,
};
int main()
{
enum Color c=BLUE;
printf("%d %d %d",RED,GREEN,BLUE);//输出默认的0 1 2
return 0;
}
3.联合体(共用体)
union Un
{
char c;
int i;
};
int main()
{
union Un u;
printf("%d\n",sizeof(u));//i和c不能同时使用
面试题(判断当前计算机的大小端数据)
(1)大小端字节序问题
int check_sys
{
union Un
{
int i;
char c;
}u;
u.i=1;
return u.c;//c本是char,以int型返回
}
int main()
{
int a=1; //寄存器里用16进制0x00000001 ,若小端,即01 00 00 00(<-------方向读取),
int ret=check_sys(); 大端,即00 00 00 01(------->方向读取)
if(1==ret) //转化成char*,是为了取一个字节看是00/01
{
printf(“小端”);
}
else printf("大端");
//int a=0x11223344;//11是高字节,44是低字节
//低地址------------------------>高地址
//....[][][][][11][22][33][44][][][][][][]...大端字节序存储模式
//....[][][][][44][33][22][11][][][][][][]...小端字节序存储模式(低对低)
(2)大小的计算
最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍
union Un
{
int a;//4
char arr[5];//字符数组的对齐数按照单个char来算~1,vs编译器中默认对齐数为8,
} 大小为8
实战项目(通讯录)
功能
1.存放1000个好友的信息
名字,电话,性别,住址,年龄
2.增加好友的信息
3.删除指定名字的好友信息
4.查找好友信息
5.修改好友信息
6.打印好友信息
7.排序
#define _CRT_SECURE_NO_WARNINGS 1//避免因为使用scanf,strcpy等不安全函数而报错
#define MAX 1000
#define MAX_NAME 20
#define MAX_SEX 5
#define MAX_TELE 12
#define MAX_ADDR 30
#include
#include
struct PeoInfo
{
char name[MAX_NAME];
int age;
char sex[MAX_SEX];
char tele[MAX_TELE];
char addr[MAX_ADDR];
};
//创建通讯录类型
struct Contact
{
struct PeoInfo data[MAX];
int size;//记录当前已经有的元素个数
};
enum Option
{
EXIT,//0
ADD, //1
DEL, //2
SEARCH,
MODIFY,
SHOW,
SORT
};//用枚举来把case中的0 1 2 3等替换,增加代码的可读性
void InitContact(struct Contact *ps)
{
memset(ps->data,0,sizeof(ps->data));//将数组内元素设为0,用memset
ps->size=0;
}
void menu()
{
printf("****************************************\n");
printf("*****1.add 2.del *********\n");
printf("*****3.search 4.modify *********\n");
printf("*****5.show 6.sort *********\n");
printf("*****0.exit *********\n");
printf("****************************************\n");
}
void Addcontact(struct Contact *ps)
{
if(ps->size==MAX)
{
printf("通讯录已满,无法增加");
}
else
{
printf("请输入名字:>");
scanf("%s",ps->data[ps->size].name);//以%s的形式输入字符数组,引用时只写数组的名字
printf("请输入年龄:>");
scanf("%d",&(ps->data[ps->size].age));//注意不是数组形式时,要用&
printf("请输入性别:>");
scanf("%s",ps->data[ps->size].sex);
printf("请输入电话:>");
scanf("%s",ps->data[ps->size].tele);
printf("请输入住址:>");
scanf("%s",ps->data[ps->size].addr);
ps->size++;
printf("添加成功\n");
}
}
int FindByName(const struct Contact *ps,char *name)
{
int i=0;
for(i=0;isize;i++)
{
if(0==strcmp(ps->data[i].name,name));//字符串比较不用==,0表示==
{
return i;
}
}
return -1;//找不到
}
void Delcontact(struct Contact *ps)
{
char name[MAX_NAME];
printf("请输入要删除人的名字:");
scanf("%s",name);
//1.查找要删除的人的位置
int pos=FindByName(ps,name);
/*int i=0;
for(i=0;isize;i++)
{
if(0==strcmp(ps->data[i].name,name));//字符串比较不用==,0表示==
{
break;
}
}删查改都要用到这一段,打包到一个FindBy函数里*/
//2.删除
if(-1==pos)
printf("要删除的人不存在");
else
{
int j=0;
for(j=pos;j<(ps->size)-1;j++)
{
ps->data[j]=ps->data[j+1];
}
ps->size--;
printf("删除成功");
}
}
void SearchContact(const struct Contact *ps)
{
char name[MAX_NAME];
printf("请输入要查找人的名字:");
scanf("%s",name);
int pos=FindByName(ps,name);
if(pos==-1) printf("要查找的人不存在");
else
{
printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","名字","年龄","性别","电话","住址");
printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n",
ps->data[pos].name,
ps->data[pos].age,
ps->data[pos].sex,
ps->data[pos].tele,
ps->data[pos].addr);
}
}
void ModifyContact(struct Contact *ps)
{
char name[MAX_NAME];
printf("请输入要修改人的名字");
scanf("%s",name);
int pos=FindByName(ps,name);
if(pos==-1) printf("修改人的信息不存在");
else
{
printf("请输入名字:>");
scanf("%s",ps->data[pos].name);//以%s的形式输入字符数组,引用时只写数组的名字
printf("请输入年龄:>");
scanf("%d",&(ps->data[pos].age));//注意不是数组形式时,要用&
printf("请输入性别:>");
scanf("%s",ps->data[pos].sex);
printf("请输入电话:>");
scanf("%s",ps->data[pos].tele);
printf("请输入住址:>");
scanf("%s",ps->data[pos].addr);
ps->size++;
printf("修改完成\n");
}
}
void Showcontact(const struct Contact *ps)//因为只是显示,为了避免误操作改变信息,加上const
{
if(ps->size==0)
{
printf("通讯录为空");
}
else
{
int i=0;
printf("%-20s\t%-4s\t%-5s\t%-12s\t%-20s\n","名字","年龄","性别","电话","住址");//加上负号,左对齐
for(i=0;isize;i++)
{
printf("%-20s\t%-4d\t%-5s\t%-12s\t%-20s\n",
ps->data[i].name,
ps->data[i].age,
ps->data[i].sex,
ps->data[i].tele,
ps->data[i].addr);
}
}
}
int main()
{
int input=0;
struct Contact con;/*int size=0;
//创建通讯录
struct PeoInfo con[MAX];*/
//初始化通讯录
InitContact(&con);
do
{
menu();
printf("请选择:>");
scanf("%d",&input);
switch(input)
{
case ADD:
Addcontact(&con);
break;
case DEL:
Delcontact(&con);
break;
case SEARCH:
SearchContact(&con);
break;
case MODIFY:
ModifyContact(&con);
break;
case SHOW:
Showcontact(&con);//结构体传参传地址,效率更高,这个函数为了显示信息是否添加成功
break;
case SORT:
break;
case EXIT:
printf("退出通讯录");
break;
default:
printf("选择错误");
break;
}
}while(input);
return 0;
}