[Linux]Linux_os_overview_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的流程

  1. 拆分成单独的c文件

  2. 自定义*.h头文件

    1. 头文件的写法

      #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
      
  3. 写makefile文件

    1. 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个要素:

project
makefile
bin
include
obj
src
可执行文件
*.h
*.o
makefile2
*.c
makefile1

在这里插入图片描述

其中

  • 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 $@
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值