结构体
结构体存储
1.内存对齐:
1.存放结构体成员变量,必须保证前面的长度为成员变量所占空间大小的整数倍
2.结构体整体的大小必须为最大类型长度的整数倍
(1)定义了一个的结构体变量d,d所占空间空间大小为12个字节
struct date
{
char a; //1 + 3
int year; //4
int mon; //4
int day; //4
}
struct date d; //sizeof(d)==12;
(2)定义了一个的结构体变量d,d所占空间空间大小为12个字节
struct s
{
char a; //1+3,a占1个字节,空3个字节,共4个字节-是int的整数倍
int b; //4
short c; //2+2 c占2个字节,空2个字节,整个空间才是int类型的整数倍
}d;
sizeof(d)==12;
结构体传参
(1)返回结构体类型变量的值
/*返回结构体类型变量的值*/
struct date Gettmp(void)
{
struct date tmp;
scanf("%d%d%d",&tmp.year,&tmp.mon,&tmp.day);
return tmp;
}
(2)结构体变量传参
/*结构体变量传参*/
int Output(struct date d)
{
printf("%d-%d-%d\n",d.year,d.mon,d.day);
return 0;
}
(3)结构体地址传参,输入数据
/*结构体地址传参,输入数据*/
int Input2(struct date *p)
{
scanf("%d%d%d",&p->year,&p->mon,&p->day);
return 0;
}
结构体数组
#include<stdio.h>
struct student
{
char name[20];
char sex;
int age;
};
void Input(struct student *pstu,int len)
{
/*for(int i=0;i<len;i++)
{
scanf("%s",pstu->name);
scanf(" %c",&pstu->sex);//" %c"不接受'\n'
scanf("%d",&pstu->age);
}*/
for(int i=0;i<len;i++)
{
gets(pstu->name);
scanf("%c",&pstu->sex);
scanf("%d",&pstu->age);
getchar(); //避免接收剩余的'\n'
}
}
void Output(struct student *pstu,int len)
{
int i=0;
for(i=0;i<len;i++)
{
printf("姓名:%s 性别%c 年龄%d\n",pstu->name,pstu->sex,pstu->age);
}
}
int main()
{
struct student s[3]={
{"张三",'m',23},
{"李四",'f',25},
{"王五",'m',26},
};
struct student s2[2];
/* for(int i=0;i<3;i++)
{
printf("%s ",s[i].name);
printf("%c ",s[i].sex);
printf("%d\n",s[i].age);
}*/
Input(s2,2);
Output(s2,2);
}
共用体(联合体)
共用体中的变量共享一块存储空间,空间长度为最大类型的长度
union s
{
char a;
int b;
};
测试一个硬件平台是大端平台?小端平台?
存放数据0x11223344
1.小端:内存低地址存放低数据位称为内存小端
存储单元 存放的数据 0x2000 0x44 0x2001 0x33 0x2002
0x22 0x2003 0x11 2.大端:内存低地址存放高数据位称为内存大端
存储单元 存放的数据 0x2000 0x11 0x2001 0x22 0x2002
0x33 0x2003 0x44
(1)第一种方式:
#include<stdio.h>
int main()
{
int a=0x11223344;
if(*(char *)&a==0x44)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
(2)第二种方式,
设置共用体类型,判断数字1在内存中的存储位置,如果是大端存放,a中的数据就是0,小端则是1
union s
{
char a;
int b;
};
#include<stdio.h>
union s
{
char a;
int b;
};
int main()
{
union s s1;
s1.a=1;
if(s1.a)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
}
枚举类型
1.枚举常量第一个值默认为0,后面的枚举常量为前一个枚举常量的值+1
2.枚举类型对应的变量的值应该为枚举常量中的值之一
3.枚举常量可以让代码提高可读性
#include<stdio.h>
enum week
{
Monday=1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
};
int main()
{
enum week day;
scanf("%d",(int *)&day);
if(Monday==day)
{
printf("星期一\n");
}
else if(Tuesday==day)
{
printf("星期二\n");
}
else if(Wednesday==day)
{
printf("星期三\n");
}
else if(Thursday==day)
{
printf("星期四\n");
}
else if(Friday==day)
{
printf("星期五\n");
}
else if(Saturday==day)
{
printf("星期六\n");
}
else
{
printf("星期天\n");
}
}
位运算
& 按位与 &0得0
| 按位或 |1置1
^ 按位异或 相同为0 相异为1
~ 按位取反
<< 左移
>> 右移 让数据缩小 num /= 2 ^ n
(1)不改变其余位的前提下,让第n位置1
int num: 1110 1011
num = num | (1 << n);
(2) 不改变其余位的前提下,让第n位置0
int num:1110 1011
num = num & (~(1 << n));
(3)实现两个数交换的三种方法
^实现两个数的交换
int a=100;
int b=200;
a=a^b;
b=a^b;
a=a^b;
(2)设置中间变量
int a=100;
int b=200;
int t=0;
t=a;
a=b;
b=t;
(3)求和再减
int a=100;
int b=200;
int sum=a+b;
a=sum-a;
b=sum-b;
运算符优先级:
括号 > 单目 > 双目 > 三目 > 赋值 > 逗号
双目:
算数 > 移位 > 关系 > 位运算 > 逻辑