Linux_概述_2
一、函数指针
二、函数指针数组
三、3个复杂数据结构
1、结构体struct
1.1、给结构体内部成员赋值的三种方法
- 定义结构体变量
typedef struct student { int age; char name[10]; int score[6]; }STU;//定义结构体数据类型 int main() { STU stu;//定义结构体变量 stu.age = 10;//使用点给结构体内部的成员赋值 stu.name = {"zhangsan"}; stu.score[0] = 100; return 0; }
- 定义结构体指针
typedef struct student { int age; char name[10]; int score[6]; }STU;//定义结构体数据类型 int main() { STU stu;//定义结构体变量 STU* p = &stu;//定义结构体指针变量,使其指向结构体变量,必须要让结构体指针指向结构体变量 p->age = 10;//使用箭头指向给结构体内部的成员赋值 p->name = {"zhangsan"}; p->score[0] = 100; return 0; }
- 直接输入
typedef struct student { int age; char name[10]; int score[6]; }STU;//定义结构体数据类型 int main() { STU stu;//定义结构体变量 stu = {25,"Luli",{100,100,100}};//定义的时候就要给内部成员赋值 return 0; }
1.2、使用scanf给结构体内部成员输入值时,&取地址符的加与不加取决于内部成员的数据类型,不受.和->限制
typedef struct student
{
int age;
char name[10];
int score[6];
}STU;//定义结构体数据类型
int main()
{
STU stu;//定义结构体变量
scanf("%d",&stu.age);
scanf("%s",stu.name);
scanf("%d",&stu.score[0]);
return 0;
}
typedef struct student
{
int age;
char name[10];
int score[6];
}STU;//定义结构体数据类型
int main()
{
STU stu;//定义结构体变量
STU* p = &stu;//定义结构体指针变量,使其指向结构体变量,必须要让结构体指针指向结构体变量
scanf("%d",&p->.age);
scanf("%s",p->name);
scanf("%d",&p->score[0]);
return 0;
}
1.3、结构体嵌套与结构体指针嵌套
#include <stdio.h>
//结构体嵌套
struct people
{
char name[20];
int age;
};
struct student
{
int inode;
struct people peo;
};
int main()
{
struct student stu;
printf("%d\n",stu.inode);
printf("%d\n",stu.peo.age);
printf("%s\n",stu.peo.name);
/*
struct student stu;
struct student *s = &stu;
printf("%d\n",s->inode);
printf("%d\n",s->peo.age);
printf("%s\n",s->peo.name);
*/
return 0;
}
#include <stdio.h>
//结构体指针嵌套
struct people
{
char name[20];
int age;
};
struct student
{
int inode;
struct people* peo;
};
int main()
{
struct student stu;
struct people p;
struct student* s = &stu;
s->peo = &p;
scanf("%d%d%s",&s->inode,&s->peo->age,s->peo->name);
printf("%d\n",s->inode);
printf("%d\n",s->peo->age);
printf("%s\n",s->peo->name);
return 0;
}
1.4 结构体综合项目
-
用malloc开辟三个结构体类型的空间,输入学生的姓名,年龄,成绩,然后对学生的姓名和年龄进行排序,并且计算出每个学生的平均成绩。(输入,输出,开辟,姓名,成绩,平均成绩,菜单)
#include <stdio.h> #include <malloc.h> #include <string.h> typedef struct student { char name[20]; int age; int grade[3]; int average; }STU; void INPUT(STU* pstu,int n)//输入 { int i,j; for(i = 0; i < n; i++)//每个人 { printf("第%d个人的姓名和年龄为:",i+1); scanf("%s",(pstu+i)->name);//姓名 scanf("%d",&(pstu+i)->age);//年龄 for(j = 0; j < n; j++)//输入每个人的三科的成绩 { printf("第%d个人的第%d门成绩为:",i+1,j+1); scanf("%d",&(pstu+i)->grade[j]); } printf("\n"); } printf("\n"); } void OUTPUT(STU* pstu,int n)//输出 { int i,j; for(i = 0; i < n; i++)//每个人 { printf("第%d个人的姓名和年龄为:",i+1); printf("%s %d",(pstu+i)->name,(pstu+i)->age);//姓名和年龄 printf("\n"); for(j = 0; j < n; j++)//输入每个人的三科的成绩 { printf("第%d个人的第%d门成绩为:",i+1,j+1); printf("%d",(pstu+i)->grade[j]); printf("\n"); } } printf("\n"); } void AVERAGE(STU* pstu,int n)//求每个人成绩的平均值 { int i,j,sum = 0; int aver = 0; for(i = 0; i < n; i++) { for(j = 0; j < n;j++) { sum = (pstu+i)->grade[j] + sum; } aver = sum / 3; sum = 0; (pstu+i)->average = aver; } for(i = 0; i < n ;i++) { printf("%s的平均成绩为:%d\n",(pstu+i)->name,(pstu+i)->average); } printf("\n"); } void NAME_SORT(STU* pstu,int n)//按姓名排序 { int i,j; //char t[20] = {0}; STU t; for(i = 0; i < n-1; i++) { for(j = 0; j < n-1-i; j++) { if(strcmp((pstu+j+1)->name,(pstu+j)->name) < 0) { t = *(pstu+j+1); *(pstu+j+1) = *(pstu+j); *(pstu+j) = t; } } } printf("按姓名排序后为\n"); OUTPUT(pstu,n); /* for(i = 0; i < 3; i++) { printf("%s\n",(pstu+i)->name);//姓名 } */ } void GRADE_SORT(STU* pstu)//按成绩排序 { /* for(i = 0; i <= 3; i++) { for(j = 2;j >= i;j--) { if() } } */ } /*struct student OPEN(pstu) { STU* pstu = (STU *)malloc(sizeof(STU)*3); return pstu; } */ STU *MALLOC(STU** pstu,int n) { *pstu = malloc(sizeof(STU)*n); if(NULL == pstu) { printf("内存分配失败\n"); } else { printf("内存分配成功\n"); } printf("\n"); return *pstu; } void menu() { printf("1------分配空间\n"); printf("2------输入\n"); printf("3------输出\n"); printf("4------求每个人的平均成绩\n"); printf("5------按姓名排序\n"); // printf("6------按成绩排序\n"); printf("7------退出\n"); } int main() { STU a; STU *s = &a; int n = 0; int option = 0; // STU* s = (STU *)malloc(sizeof(STU)*3); while(1) { menu(); printf("请输入你要进行的操作:"); scanf("%d",&option); switch(option) { case 1:s = MALLOC(&s,3);break; //STU* s = (STU *)malloc(sizeof(STU)*3);break; case 2:INPUT(s,3);break; case 3:OUTPUT(s,3);break; case 4:AVERAGE(s,3);break; case 5:NAME_SORT(s,3);break; // case 6:GRADE_SORT(s,n);break; case 7:break; } if (7 == option) { break; } } free(s); return 0; }
2、共用体union
union AA
{
char name[20];
int age;
float height;
};
3、枚举enum
enum A
{
mon,
tue,
wed,
thr,
fri,
sat,
sun,
};
- 特性
- 若枚举内的元素未赋值,则元素值从零开始往后递增(此时枚举内的元素的值分别为0,1,2,3,4,5,6)
- 若枚举内的元素已赋值,则之后元素的值从赋值的地方往后递增,之前的元素的值依据从零开始往后递增(若此时给thr赋值为5,则此时枚举内的元素的值分别为:0,1,2,5,6,7,8)
4、结构体与共用体的字节对齐
- 在64位操作系统中,一般最大按照8个字节为基准,在32位操作系统中,按照4个字节为基准,如果没有超过4各字节(8个字节),就按照结构体内最大的那个数据类型去分配
- 结构体:对于结构体内部元素的定义,一般按照数据类型的大小,从小到大定义数据
struct AA { char name[25]; int age; double a; };//40字节 struct AA { char a; int b; short c; };//12字节 struct AA { char a; short b; int c; };//8个字节
- 共用体:共用体内部的所有元素的起始地址一样
union AA { int arr[10]; char b; char name[25]; };//union内的元素共用元素内存占用最大的一片空间,此案例三个成员共同占用25个字节的空间
四、makefile
1、 makefile简介
- make是一个工程管理器,用来管理多文件联合编译。其将不同的.c(有某种关系)文件编译成一个可执行文件
2、gcc编译的四个阶段
- 预处理:将hello.c预处理输出hello.i文件(展开头文件,替换宏,去掉注释)
gcc -E hello.c -o hello.i
- 编译:将预处理输出文件hello.i编译成hello.s文件(生成汇编指令)
gcc -S hello.i -o hello.s
- 汇编:将编译输出文件hello.s编译输出hello.o文件(生成系统可识别的二进制代码)
gcc -c hello.s -o hello.o
- 链接:将汇编输出文件hello.o链接成最终可执行文件hello(生成系统可识别的二进制代码)
gcc hello.o -o hello
3、makefile文件的写法
-
写makefile,将最后一步放在最上面写,将第一步放在最下面写
-
make会根据时间戳管理文件
目标:依赖 [tab]关系表 1.o:1.c gcc -c 1.c -o 1.o
4、多文件makefile的流程
-
拆分成单独的c文件
-
自定义*.h头文件
-
头文件的写法
#ifndef TEST_H
#define TEST_H
//防止头文件被重复定义
1.头文件(库函数的头文件)2.结构体/共用体
3.宏定义
4.枚举
5.子函数的声明
#endif
例如:
#ifndef _STUDENT_H_ #define _STUDENT_H_ //头文件(库函数的头文件) #include <stdio.h> #include <malloc.h> #include <string.h> //结构体 typedef struct student { char name[20]; int age; int grade[3]; int average; }STU; //子函数的声明 void INPUT(STU* pstu,int n); void OUTPUT(STU* pstu,int n); void AVERAGE(STU* pstu,int n); void NAME_SORT(STU* pstu,int n); STU *MALLOC(STU** pstu,int n); void menu(); #endif
-
-
写makefile文件
-
makefile的写法
目标:依赖
[tab]关系表例如:
App:average.o input.o main.o malloc.o menu.o output.o sort.o gcc *.o -o App average.o:average.c//average.o为目标,average.c为依赖 gcc -c average.c -o average.o//关系表 input.o:input.c gcc -c input.c -o input.o main.o:main.c gcc -c main.c -o main.o malloc.o:malloc.c gcc -c malloc.c -o malloc.o menu.o:menu.c gcc -c menu.c -o menu.o output.o:output.c gcc -c output.c -o output.o sort.o:sort.c gcc -c sort.c -o sort.o .PHONY:clean//这里清除操作可以用别的名字 clean: rm *.o rm App
-
5、makefile嵌套
实现makefile嵌套需要的5个要素:
其中
-
makefile:makefile管理src和obj里面的makefile
all: make -C ./src/ make -C ./obj/ .PHONY:clean clean: rm ./obj/*.o rm ./bin/App
#执行src和obj下的makefile的 #添加系统预定义变量 CC=gcc CFLAGS= -c -g -Wall RM=rm -rf OBJ=App OBJS=main.o input.o output.o malloc.o menu.o average.o sort.o #将预定义变量添加到工程 export CC CFLAGS RM OBJ OBJS all: make -C ./src/ make -C ./obj/ .PHONY:clean clean: ${RM} ./obj/${OBJS} ${RM} ./bin/${OBJ}
-
bin:bin文件夹存放生成的可执行文件
-
include:include文件夹存放用户自定义的头文件
-
obj:obj文件夹存放所有的.o文件,以及完成将所有的.o文件,生成可执行文件,并把可执行文件移动到bin文件夹中的makefile文件
App:main.o input.o output.o malloc.o menu.o sort.o average.o gcc *.o -o App mv App ../bin/
App:${OBJS}#main.o input.o output.o malloc.o menu.o sort.o average.o ${CC} ${OBJS} -o ${OBJ} mv ${OBJ} ../bin/
-
src:src文件夹存放所有的.c文件,以及完成将所有的.c文件,生成.o文件,并把.o文件移动到obj文件夹中的makefile文件
all:average.o input.o main.o malloc.o menu.o output.o sort.o mv *.o ../obj/ average.o:average.c gcc -c average.c -o average.o input.o:input.c gcc -c input.c -o input.o main.o:main.c gcc -c main.c -o main.o malloc.o:malloc.c gcc -c malloc.c -o malloc.o menu.o:menu.c gcc -c menu.c -o menu.o output.o:output.c gcc -c output.c -o output.o sort.o:sort.c gcc -c sort.c -o sort.o
all:${OBJS}#average.o input.o main.o malloc.o menu.o output.o sort.o mv *.o ../obj/ average.o:average.c ${CC} ${CFLAGS} $< -o $@ input.o:input.c ${CC} ${CFLAGS} $< -o $@ main.o:main.c ${CC} ${CFLAGS} $< -o $@ malloc.o:malloc.c ${CC} ${CFLAGS} $< -o $@ menu.o:menu.c ${CC} ${CFLAGS} $< -o $@ output.o:output.c ${CC} ${CFLAGS} $< -o $@ sort.o:sort.c ${CC} ${CFLAGS} $< -o $@