1.结构体
结构体是一些值得集合,这些值称之为成员变量。结构体得每个成员变量可以是不同类型得变量。
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
struct Student{
char name[20];
int age;
char sex[10];
} Stu;//全局变量
struct //匿名结构体类型,只能使用一次。 且声明得指针类型不能获取地址p=&s2是非法得
{
char name[20]
}s2,*p;
int main()
{
struct Student s1;//局部变量
Stu.name="cfh";
Stu.age=20;
Stu.sex="male";
s1={"abc",12,"female};//初始化
system("pause");
return 0;
};
结构体的自引用
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
//链表的自引用
struct Node0{
char name[20];
int age;
struct Node0 next;
} ;//链表错误示范1 -> sizeof无法计算大小
typedef struct
{
int age;
Node1* pp;
}Node1;//链表错误示范2 -> 非法,矛盾
struct Node{
char name[20];
int age;
struct Node *next;
} ;//链表正确示范1 最后一个链表指针置空->NULL
typedef struct Node2
{
int age;
Node3* ptr;
}Node3;//链表正确示范1
int main()
{
system("pause");
return 0;
};
3.结构体内存对齐
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<stddef.h>
//结构体大小不仅跟内部数据类型大小相关,还跟顺序相关
struct Node0{
char c1;//1byte
int age;//4byte
char c2;//1byte
}s1,s2;//大小12
struct Node1{
char c1;//1byte
char c2;//1byte
int age;//4byte
}s3,s4;//大小8
int main()
{
printf("%d\n",offsetof(struct Node1,c1));//->需要引入stddef.h头文件
printf("%d\n",offsetof(struct Node1,c2));
printf("%d\n",offsetof(struct Node1,age));
printf("%d\n",sizeof(s1));
printf("%d\n",sizeof(s3));
system("pause");
return 0;
};
4.结构体传参
5.位段:位段的声明与结构体类似,有两个不同(1).位段的成员必须是int,unsigned int 或者signed int,(2).位段的成员名后面有一个冒号和一个数字。
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
struct A{//A是一个位段类型->用以节省空间的
int _a:2;//意思是_a只给2个bit位
int _b:3;//意思是_b只给3个bit位 ->以int 的4个字节位单位步进增加
int _c:10;
} s1;
int main()
{
printf("%d\n",sizeof(struct A));//->4个byte
system("pause");
return 0;
};
每一次开辟出来的空间占用后若未使用完,下一个元素的内存若大于剩下的空间,则需重新开辟空间,多余的空间空置。
6.枚举 :把可能的值一一列举
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
enum NUM{//默认从零开始计数加一,可以赋初值
ADD=1,
DEL,
SUB,
PRO
};
int main(){
int input;
scanf("%d",&input);
switch(input){
case ADD: printf("ADD");break;
case DEL:printf("DEL");break;
case SUB:printf("SUB");break;
default :printf("PRO");break;
};
system("pause");
}
#define 与enum之间的区别
7.联合(共用体) :一种特殊的自定义类型,包含一系列的成员,特征是这些成员公用一块空间。
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
struct Student{
int a;
char c;
};
union Un{
int a;
char c;
};
int main(){
union Un u;
printf("%d\n",sizeof(u));
printf("%p\n",&u);
printf("%p\n",&(u.c));
printf("%p\n",&(u.a));
system("pause");
}
union Un{
char arr[5];//5->char 对应的对齐数为1 最大成员内存为5.但应该是最大对齐数的整数倍,故为8
int a;//4 对齐数为4
};//占用空间8
8.动态内存开辟:
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
#define INMAX 0xFFFFFFFF
// C99标准支持的变长数组
//变长数组->int n=0;scanf("%d",&n);
// int arr[n];
int main(){
int a[10]={0};
//动态内存开辟
int *p=(int*)malloc(40);
if(p==NULL)
{
printf("%s\n",strerror(errno));//->引入error.h文件
return 1;
}
/*申请内存过大错误案例
int *p=(int*)malloc(INMAX);
*/
//使用
int i=0;
for (;i<10;i++){
*(p+i)=i;
}
for (i=0;i<10;i++){
printf("%d\n",*(p+i));
}
//没有free 并不是说内存空间不回收了 当程序退出的时候,系统会自动回收内存空间
//内存泄漏:内存一直不释放且倍占据,相当于丢失了这一部分。
free(p);//->p指向的位置不变,但是里面的东西置空了
p=NULL;//->置空,让其找不到原始的地址和数据
system("pause");
return 0;
}
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
#define INMAX 0xFFFFFFFF
int main(){
int a[10]={0};
//动态内存开辟
int *p=(int*)malloc(40);
if(p==NULL)
{
printf("%s\n",strerror(errno));//->引入error.h文件
return 1;
}
//使用
int i=0;
for (;i<10;i++){
*(p+i)=i+1;
}
for (i=0;i<10;i++){
printf("%d\n",*(p+i));
}
//扩容->根据情况判断是否->开辟新的空间存储然后释放原有的空间或者在后面直接添加
int* ptr=(int*)realloc(p,80);//不能直接将扩容的对象返回的值直接返回给自身,若申请空间失败,则原有内容也会失去。故使用新的指针变量接收。
if(ptr!=NULL)
{
p=ptr;
return 1;
}
for (i=0;i<10;i++){
printf("%d\n",*(p+i));
}
free(p);//->只能释放所有开辟的空间
p=NULL;
system("pause");
return 0;
}
动态开辟若未释放则可能会找出内存泄露,只有free能够释放内存
9.柔性数组
10.文件操作
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
int main(){
//打开文件
FILE* pf=fopen("E:\\WordFile\\text.txt","w");
if(pf==NULL){
printf("%s\n",strerror(errno));
return 1;
}
//写文件
for (char i='a';i<='z';i++){
fputc(i,pf);
}
fclose(pf);
pf=NULL;
//打开文件
FILE* ch=fopen("E:\\WordFile\\text.txt","r");
if(ch==NULL){
printf("%s\n",strerror(errno));
return 1;
}
//读文件
char ch1;
while((ch1=fgetc(ch)!=EOF)){
printf("%c\n",ch1);
}
//关闭文件
fclose(ch);
ch=NULL;
system("pause");
return 0;
}
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<error.h>
int main(){
//打开文件
FILE* pf=fopen("E:\\WordFile\\text.txt","w");
if(pf==NULL){
//printf("%s\n",strerror(errno));
perror("fopen");//打印错误信息
return 1;
}
//写文件
fputs("hello bit",pf);
fclose(pf);
pf=NULL;
system("pause");
return 0;
}
/*
printf(),在控制台打印输出信息
fprintf(),直接在文件中打印信息
*/
11.预处理
12.#define 定义宏
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) X*X //注意:宏是直接将参数替换到表达式中->所以一般最好在上面加括号 例如 (X)*(X)
int main()
{
int x,y;
x=SQUARE(5);//5*5=25
y=SQUARE(4+1);//4+1*4+1=9
printf("x=%d\ny=%d\n",x,y);
system("pause");
return 0;
};
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) printf("X=%d\n",X);
int main()
{
int x=10;
int y=20;
printf("x=%d\ny=%d\n",x,y);
SQUARE(x);
SQUARE(y);
printf("hello ""bit");//->两个双引号会自动和合并为一个双引号
system("pause");
return 0;
};
#和##号的使用->在宏使用中可以替代变量名,见下代码,要加双引号
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define SQUARE(X) printf(""#X"=%d\n",X);//->#X转化为双引号加变量名
int main()
{
int x=10;
int y=20;
printf("x=%d\ny=%d\n",x,y);
SQUARE(x);
SQUARE(y);
printf("hello ""bit");//->两个双引号会自动和合并为一个双引号
system("pause");
return 0;
};
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define CAT(X,Y) X##Y
int main()
{
int xy=30;
int y=20;
int x=10;
printf("x=%d\ny=%d\nxy=%d\n",x,y,CAT(x,y));
system("pause");
return 0;
};
#include <string.h>
#include <stdio.h>
#include<stdlib.h>
#include<windows.h>
#define MAX(X,Y) ((X)>(Y) ? (X):(Y));
int main()
{
int x=5;
int y=4;
int m=MAX(x++,y++);//->(x++)>(y++)?x++:y++;
//5>4?比较之后x=6,y=5,即m=6,赋值之后 x=7,y++未执行所以不变为5;
printf("m=%d\nx=%d\ny=%d\n",m,x,y);
system("pause");
return 0;
};
宏和函数的对比