第八章 函数与宏定义

8.1函数的概念

为什么要使用函数?

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

  • 使用函数可使程序清晰、精炼、简单、灵活。
  • 函数就是功能。一个函数实现一个功能。
    函数名应反映其代表的功能。
  • 在设计较大程序时,一般把它分为若干个程序模块,每一个模块实现一个特定的功能。
  • 一个C程序可由一个主函数和若干个其他函数构成。由主函数调用其他函数,其他函数也可以互相调用。
  • 同一个函数可以被一个或多个函数调用任意多次。

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

C语言的函数分为两类:
①系统定义的标准函数,又称为库函数。
  函数声明一般是放在系统的include目录下以.h为后缀的头文件中,如在程序中要用到某个库函数,必须在调用该函数之前用#include<头文件>命令将库函数信息包含到本程序中。
②自定义函数。
  按要求设计
C语言程序设计的核心之一:自定义函数。

8.1.1 函数的定义

  • 自定义函数
[存储类型符] [返回值类型符]  函数名([形参说明表])
{<函数语句体>
}

说明:
1.[存储类型符] 指的是函数的作用范围,只有两种形式:static和extern。
 static说明的函数称为内部函数,只能作用于其所在的源文件,
 extern说明的函数称为外部函数,可被其他源文件中的函数调用。

  • 缺省情况为extern

2.[返回值类型符] 指的是函数体语句执行完成后,函数返回值的类型。
如int,float,char等。

  • 若函数无返回值,则用空类型void来定义函数的返回值。
  • 默认情况为int型(有些编辑器不支持默认情况)。

3**.函数名**由任何合法的标识符构成

  • 建议将函数名的命名与函数内容有一定关系

4.[形参说明表] 是一系列用逗号分开的形参变量说明。
如:int x,int y,int z,
表示形参变量有三个:x,y,z。类型都是int型的。
注意: 不能直接写成:int x,y,z。
5.在古典式函数定义中,[形参表] 只要形参名,不要类型名。如:x,y,z。
表示形参变量有三个。形参变量的类型通过型参说明 语句说明。

  • [行参说明表]或[形参表]都可以缺省,缺省时表示函数无参数。


6. 函数语句体是放在一对花括号{ }中,由局部数据类型描述和功能实现两部分组成。

  • 函数返回语句。
    通常用返回语句来结束函数的调用。
  • 两种形式的返回语句:
    ①函数无返回值的情况
    return
    ②函数有返回值的情况
    return(表达式的值);

8.1.2 函数的声明和调用

通常情况下,自定义的函数在使用之前要先进行函数声明,才能在程序中进行函数调用。
1.函数声明
函数声明语句的形式:
[存储类型符]   [返回值类型符]  函数名([形参说明表]);
如:int abs_sun(int m,int n);
(abs是求绝对值函数)
2.函数调用函数定义好后,若不通过函数调用,不会发挥任何作用。
函数调用是通过函数调用语句来实现的。
①函数无返回值情况:
函数名([实参表]);
②函数有返回值的情况:
变量名=函数名([实参表]);
注意: 变量名的类型必须与函数的返回值类型相同。
函数调用时,会去执行函数中的语句内容,函数在执行完毕后,回到函数的调用处,继续执行程序中函数调用后面的语句。

8.1.3 函数的传值方式

函数传值的4个要点:
①对于带有参数的函数,调用时,将实参表中每一个实参的值对应的传递给每一个形参变量;
②形参变量接收到实参传来的值后,会在内存临时开辟新的空间,保存形参变量的值;
③函数执行完毕时,释放临时开辟的内存空间;
④形参的值在函数中不论是否发生变化,实参变量的值均不会发生变化。
自定义函数在程序中的使用方式有两种形式:
①先声明函数声明,再进行函数调用,函数定义放在main函数的后面。
②先定义函数,再调用函数(不需要在调用前函数声明)。
【例8.1】编写程序,通过调用函数int abs_sum(int a,int b),求任意两个整数的和。

第一种形式:先进行函数声明;
      再进行函数调用;
      最后给出函数定义。

#include<stdio.h>
int abs_sum(int m,int n);/*函数声明*/
main()
{int x,y,z;scanf("%d%d",&x,&y);z=abs_sum(x,y);   /*函数调用*/printf("|%d|+|%d|=%d\n",x,y,z);
}
int abs_sum(int m,int n)/*函数定义*/
{if(m<0)m=-m;if(n<0)n=-n;return m+n;
}

第二种形式:先定义函数;
      再调用函数
      (不需要在调用前函数声明)

#include<stdio.h>
int abs_sum(int m,int n)/*函数定义*/
{if(m<0)m=-m;if(n<0)n=-n;return m+n;
}
main()
{int x,y,z;scanf("%d%d",&x,&y);z=abs_sum(x,y);   /*函数调用*/printf("|%d|+|%d|=%d\n",x,y,z);
}

思考:
1.怎样求任意3个整数之和?
(自己写的)

 //注意if函数体后面有; //双引号内是% //返回值要赋值给一个定义好的变量//定义函数名后面有实参表,前面有存储类型符 #include<stdio.h>
int abs_sum(int a,int b,int c);/*函数声明*/
main()
{int x,y,z,q;scanf("%d%d%d",&x,&y,&z);q=abs_sum(x,y,z);   /*函数调用*/ printf("|%d|+|%d|+|%d|=%d\n",x,y,z,q);}
int abs_sum(int a,int b,int c)/*函数定义*/
{if (a<0)a=-a;if (b<0)b=-b;if (c<0)c=-c;return a+b+c;
}

(老师教的)

//scanf双引号内没有逗号 ,双引号与变量之间有逗号 ,变量名前加&地址符
//函数定义后面没有分号 #include<stdio.h>
int abs_sum(int a,int b);
main()
{int x,y,z,sum;scanf("%d%d%d",&x,&y,&z);sum=abs_sum(abs_sum(x,y),z);printf("|%d|+|%d|+|%d|=%d",x,y,z,sum);
}
int abs_sum(int a,int b)
{if(a<0)a=-a;if(b<0)b=-b; return a+b;
}

函数传值调用的性质:
实参的值在函数调用前和函数调用后不会发生变化。
如有程序,分析程序的运行结果

#include<stdio.h>
void exchange(int a,int b)
{int temp;printf("3---a=%d,b=%d\n",a,b);temp=a;a=b;b=temp;printf("4---a=%d,b=%d\n",a,b);
}
main()
{int x=10,y=20;printf("1---x=%d,y=%d\n",x,y);exchange(x,y);/*函数调用*/printf("2---x=%d,y=%d\n",x,y);
}

8.2 变量的作用域和存储类型

根据变量的作用域不同,可分为局部变量和全局变量两种。
1.变量的作用域
变量的作用域:变量起作用的范围
①局部变量:在函数内部或某个控制块的内部定义的变量。

  • 局部变量的作用域:函数内部
  • 作用:增强了函数模块的独立性

②全局变量:在函数外面定义的变量称为全局变量

  • 全局变量的作用域:从该变量定义的为止开始,直到源文件结束。
  • 作用:在同一文件中,所有函数都可以引用全局变量。增强了各函数间数据的联系。
    变量的存储类型
  • 变量的存储类型指的是变量的存储属性,它说明变量占用存储空间的区域。
  • 在内存中,供用户使用的存储区域由== 程序区、静态存储区和动态存储区== 3部分组成。
  • 变量的存储类型:auto、register、static和extern 4种。
    ①auto型变量存储在内存的动态存储区;
    ②register型变量保存在寄存器中;
    ③static型和extern变量存储器在静态存储区。
  • 局部变量的存储类型默认值为auto型(动态存储区)。
  • 全局变量的存储类型默认值为extern型(静态存储区)。
    注意:
    ①一般情况下,常用auto型register型定义局部变量。
    ②static型既可作为局部变量又可作为全局变量。
    作为局部变量时,局部变量的值将被保留,若定义时没有赋初值,则系统会自动为其赋0值;
    作为全局变量时,其有效范围为它所在的源文件,其他源文件不能使用。

【例8.2】设计一个函数long fac(int n),用来计算正整数的阶乘,编写程序进行测试。

分析:由于计算机对变量的字节长度分配有限,整型变量的最大值是一定的,因此,目前计算整数的阶乘只能针对较小的整数。假定要计算1~5的阶乘。
算法的核心思想:对于任意正整数n,如果知道(n-1)!,则n!=nx(n-1)!。可在函数中定义一个static型变量,用来保存每一次阶乘的计算结果

/*利用static型变量保留每一次阶乘的值*/
#include<stdio.h>
long fac(int n) /*fac()是计算n!的函数*/
{static int f=1;f=f*n;return f;
}
int main()
{int i;for(i=1;i<=5;i++)printf("%d!=%ld\n",i,fac(i));
}

8.3 内部函数和外部函数

自定义的函数有两种:内部函数外部函数
1.内部函数
 若函数的存储类型为static型,则称其为内部函数(内部函数又称为静态函数),它表示在由多个源文件组成的同一个程序中,该函数只能在其所在的文件中使用,在其他文件中不可使用。

  • 内部函数的声明形式:
     static <返回值> <函数名>(<参数>);
    例如:
     static int Statistic();

2.外部函数
 若函数的存储类型定义为extern型,则称其为外部函数,它表示该函数能被其它源文件调用。

  • 函数的默认存储类型为extern型。
    【例8.2】外部函数的应用示例。下面的程序由三个文件组成:file1.c、file2.c、example8_2.c。
    在file1.c、file2.c中分别定义了两个外部函数;在example8_2.c中可以分别调用这两个函数。
//1 file1.c
/*file1.c外部函数定义*/
extern int add(int m,int n)
{return(m+n);
}
//2 file2.c
/*file2.c外部函数定义*/
extern int mod(int a,int b)
{return(a%b);
}
/*example8_2c 调用外部函数*/
#include<stdio.h>
extern int mod(int a,int b);/*外部函数声明*/
extern int add(int m,int n);/*外部函数声明*/
main()
{int x,y,result1,result2,result;printf("Please enter x and y:\n");scanf("%d%d",&x,&y);result1=add(x,y);printf("x+y=%d\n",result);if(result>0)result2=mod(x,y); /*调用file2中的外部函数*/result=result1-result2;printf("mod(x,y)=%d\n",result2);printf("(x+y)-mod(x,y)=%d\n",result);
}
  • 关于函数的几点声明

(1)在程序file1.c、file2.c中的函数定义可以不需要extern加以说明,默认为外部函数。
(2)在example6_6.c中对外部函数的声明也可以不用extern加以说明,默认为外部函数。
(3)由多个源文件组成一个程序时,main()函数只能出现在一个源文件中。
(4)由多个源文件组成一个程序时,有三种连接方式:
  ①将各源文件分别编译成目标文件,得到多个目标文件(.obj后缀),然后用连接命令把多个.obj文件连接起来。
   Turbo c的连接命令为tlink
   例如:tlink example6_6.obj+filc1.obj+file2.obj
   结果:生成一个example6_6.exe文件。
  ②建立项目文件(.prj后缀或.dsw后缀),具体操作可操作可参阅各种C语言集成开发环境说明。
  ③使用文件包含命令。(建议,8.5.2节-文件包含)(常用)
(5)如果将file1.c或file2.c中的extern改成static,则主程序在编译时无法通过。
(6)在程序file1.c或file2.c中,也可以互相调用其外部函数。

8.4 递归函数的设计与调用

  • 函数的嵌套调用:
    函数中的语句可以是对另一个函数的调用。
  • 函数嵌套调用的过程如图所示:
  • 嵌套调用属于一种线性调用关系,函数执行完成后,返回到原调用点,继续执行函数调用下面的语句。
  • 函数的递归调用
    两种递归形式:直接递归调用和间接递归调用。
    ①直接递归调用
    直接递归:
    函数直接调用自身函数。
    ②间接递归调用
    间接递归:
    函数互相调用对方函数。
  • 递归形式:

  • 可能出现的陷阱
    递归调用陷入无限递归状态。
  • 递归的限制
    并不是所有的问题都可以设计成递归函数。为了避免错误的发生,对于递归函数的设计,有严格的数学模型。
  • 递归函数的条件
    递归函数模型在数学上必须具备以下两个条件。
    ①问题的后一部分与原始问题类似。
    ②问题的后一部分是原始问题的简化。
  • 难点
    递归函数设计的难点是建立问题的数学模型,有了正确的递归数学模型,很容易写出递归函数。

【例8.5】用递归的方法求n!。

#include<stdio.h>
int main()
{long fac(int n);       //fac函数声明int n;long y;printf("please enter an integer number:");scanf("%d",&n); //输入要求阶乘的函数y=fac(n);printf("%d!=%d\n",n,y);return 0;
}
long  fac(int n)            //定义fac函数
{long f;if(n<0)                  //n<0,无解printf("n<0,data error!");else if(n==0||n==1)f=1;               //递归终止条件elsef=fac(n-1)*n;      //递归关系return(f);
}

【例8.4】有5个学生坐在一起,问第5个学生多大?他说比第4个学生打2岁。问第4个学生岁数,他说比第3个学生大2岁。问第3个学生,又说比第2个学生大2岁。问第2个学生,说第1个学生大2岁。最后问第1个学生,他说是10岁。请问第5个学生多大?

#include<stdio.h>
int main()
{int age(int n);            //对age函数的声明printf("The age of 5th student is %d\n",age(5));return 0;
}
int age(int n)              //定义递归函数
{int c;                 //c是存放函数的返回值的变量if(n==1)c=10;             //递归结束条件elsec=age(n-1)+2;     //递归公式,c的值是前面一个人的年龄加2return(c);
}

注意分析递归的终止条件

8.5 预处理

  • 预处理的作用:
    向编译系统发布信息或命令,告诉编译系统在对源程序进行编译之前应做些什么事。
  • 所有编译预处理都是以”#“开头,单占源程序的一行,放在源程序的首部。
  • 编译预处理不是C语句,行末不必加分号。
  • C语言提供预处理指令主要有3种。宏定义、文件包含和条件编译。

8.5.1宏定义

  • 两种宏定义:不带参数的宏和带参数的宏。
  • 宏定义的作用:简化程序的书写。

1.不带参数的宏

  • 定义形式:#define  宏名  字符串

说明:
①define是关键字,表示宏定义。
②宏名用标识符表示,为区别于变量,宏名一般才用大写字母。如:#define PI 3.14159
③宏的作用:将程序中的宏定义用字符串替换。
④宏名的有效范围是从定义命令之后,直到源程序文件结束,或遇到宏定义终止命令#undef为止。

2.带参数的宏

  • 定义形式:#define  宏名(参数表) 字符串

说明:
①字符串包含有参数表中的参数。
②宏替换时,将字符串中的参数用实参表中的实参替换。
【例8.6】阅读程序,了解带参数的宏定义的作用。分析程序运行的结果。

/*example了解带参数的宏定义的作用*/
#include<stdio.h>
#define F(a)(a)*b
main()
{int x,y,b,z;printf("Please enter the value of x,y:\n");scanf("%d%d",&x,&y);        //如果%d%d中间没有任何字符,输入时加空格,如果中间有逗号,输入的时候也加逗号b=x+y;z=F(x+y);printf("b=%d\nF(x+y)=%d\n",b,z);
}

特别提示:
有参数的宏定义与函数是完全不同的两个概念
【例8.6】Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上(见图6.10)。有一个老和尚想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘子,且在移动的过程中在3个坐上始终保持大盘在下,小盘在上。在移动的过程中可以利用B座,要求编程序输出移动的步骤。

解题思路:
老和尚会这样想:假如有另外一个和尚能有办法将上面63个盘子从一个座移到另一个座。那么,问题就解决了。此时老和尚只须这样做:
①命令第2个和尚将63个盘子从A座移到B座;
②自己将1个盘子(最底下的、最大的盘子)从A座移到C座;
③再命令第2个和尚将63个盘子从B座移到C座。
第二个和尚又想:如果有人能将62个盘子从一个座移到另一个座。我就能将63个盘子从A座移到B座,他是这样做的:
①命令第3个和尚将62个盘子从A座移到B座;
②自己将1个盘子从A座移到B座;
③再命令第2个和尚将62个盘子从C座移到B座。


解题思路
为了便于理解,先分析将A座上3个盘子移到C座上的过程:
①将A座上2个盘子移到B座上(借助C座)。
②将A座上1个盘子移到C座上。
③将B座上2个盘子移到C座上(借助A座)。
其中第②步可以直接实现。第①步又可用递归方法分解为:

  • 将A座上1个盘子从A座移到C座;
  • 将A座上1个盘子从A座移到B座;
  • 将C座上1个盘子从C座移到B座。

第③步可以分解为:

  • 将B座上1个盘子从B座移到C座上;
  • 将B座上1个盘子从B座移到C座上;
  • 将A座上1个盘子从A座移到C座上。
    将以上综合起来可得到移动3个盘子的步骤为:
    A→C,A→B,C→B,A→C,B→A,B→C,A→C。
    共经历7步。由此可推出;移动n个盘子要经历(2n -1)步。


由上面的分析可知:将n个盘子从A座移到C座可以分解为以下3个步骤:
 ①将A座上n=1个盘子借助C座先移到B座上;
 ②把A座剩下的一个盘移到C座上;
 ③将n-1个盘从B座借助于A座移到C座上。
上面第①步和第③步,都是把n-1个盘子从一个座移到另一个座上,采取的办法是一样的,只是座名字不同而已。为使之一般化,可以将第①步和第③步表示为:
将one座上n-1个盘子移到two座(借助three座)。只是在第①步和第②步中,one,two,three和A,B,C的对应关系不同。
因此,可以把上面3个步骤分成两类操作:
 ①将n-1个盘从一个座移到另一个座上(n>1)。这就是大和尚和小和尚做的工作,它是一个递归的过程,即和尚将任务层层下放,直到第64个和尚为止。——Hanoi函数
 ②将1个盘子从一个座上移到另一个座上。这就是大和尚自己做的工作。——move函数

#include<stdio.h>
int main()
{void hanoi(int n,char one,char two,char three);//对hanoi函数的声明int m;printf("intput the number of diskes:");scanf("%d",&m);printf("The step to move %d diskes:\n",m);hanoi(m,'A','B','C');
}
void hanoi(int n,char one,char two,char three)//定义hanoi函数
//将n个盘子从one座借助two座,移到three座
{void move(char x,char y);  //对move函数的声明if(n==1)move(one,three);      //如果只有一个盘子就直接移到即可else{hanoi(n-1,one,three,two); //递归调用Hanoi函数move(one,three);           //直接移动一个盘子hanoi(n-1,two,one,three); //递归调用hanoi函数}
}
void move(char x,char y)            //定义move函数
{printf("%c->%c\n",x,y);           //输出移动的步骤
}

把函数当前的各项值压入栈,,根据原语句开辟一个新的hanoi函数,假如新函数运行完,则从栈中取出上一个函数的各项值继续运行
在本程序中,调用递归函数hanoi,其终止条件为hanoi函数的参数n的值等于1。显然,此时不必再调用hanoi函数了,直接执行move函数即可。
在本程序中move函数并未真正移到盘子,而只是输出移盘的方案(表示从哪一个座移到哪一个座)。

仅供参考,部分内容,详细看B站

8.5.2 文件包含

  • 将另一个文件的全部内容包含到程序中,编译时,用包含文件的内容取代该预处理命令。
  • 文件包含命令的一般形式:
    #include<包含文件名>或:#include"包含文件名"
    注意:
    ①include是命令关键字,一个include命令只能包含一个文件。
    ②<>表示被包含文件在标准目录(include)中。
    ③" “表示被包含文件在指定的目录中,若只有文件名不带路径,则在当前目录中,若找不到,再到
    ④包含文件名可以是.c源文件或.h头文件。如:
     #include<stdio.h>
     #include"myhead.h”
     include"D:\myexam\myfile.c"
  • 文件包含的作用:
    ①将多个源文件拼接在一起。
     如:有文件file2.c,其内容都是自定义的函数
     另有文件file1.c,该文件有main函数
     如果在file1.c程序中要调用file2.c中的函数,可采用文件包含的形式:#include"file2.c"
    ②在对file1.c进行编译时,系统会用file2.c的内容替换掉文件包含命令#include"file2.c",然后再对其进行编译。
    ③要注意区分外部函数与文件包含的区别。
     它们都是可以在某个程序中用另一个文件中的函数,但使用的方法有所不同。

C语言程序设计(理论课)第八章 函数与宏定义相关推荐

  1. c语言用参数确认递归,C语言程序设计(第4章函数)3

    4.3 函数的调用与参数 如果一个函数要使用参数,它就必须定义接受参数值的变量. 4.3.1 形式参数与实际参数 函数定义时填入的参数我们称之为形式参数,简称形参,它们同函数内部的局部变量作用相同.形 ...

  2. c语言中注释参与程序设计的编译吗,C语言程序设计(第4章函数)6

    4.7 C语言的预处理程序与注释 C程序的源代码中可包括各种编译指令,这些指令称为预处理命令.虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境.本节将介绍如何应用预处理程序和注释简化程序开 ...

  3. C语言设计函数求最大公约数,C语言程序设计课程设计--编写函数求取两个整数m,n的最大公约数和最小公倍数.doc_在线文库www.lddoc.cn...

    C语言程序设计课程设计--编写函数,求取两个整数m,n的最大公约数和最小公倍数.doc C语言程序设计课程设计C语言程序设计课程设计评语考勤(10)纪律(10)过程(40)设计报告(30)答辩(10) ...

  4. c语言程序设计 北交,北交《C语言程序设计(专)》在线作业一 设有定义 int n 0pamp n qamp p 则下列选项中正确的赋值语句是.docx-得力文库...

    北交<C语言程序设计(专)>在线作业一 设有定义 int n 0 p amp n q amp p 则下列选项中正确的赋值语句是.docx C C语言程序设计语言程序设计 专专 1 1 单选 ...

  5. 第六章函数与宏定义实验报告(后半部分)

    实验项目:函数与宏定义实验报告 姓名:谢丽萍     实验地点:514教室       实验时间:2019 5.16 一.实验目的与要求 1.利用复化梯形公式计算定积分 ①掌握c语言中定义函数的方法 ...

  6. 第六章实验报告(函数与宏定义)

    实验项目:函数和宏定义实验 姓名:谢丽萍    试验地点:教学楼514教室    实验地点:2019 年4月30日 一.实验目的与要求 1.掌握函数的定义方法和调用规则 2.掌握在c语言程序中主调函数 ...

  7. linux驱动 打印变量,linux驱动 内核函数 变量 宏定义

    insmod modprobe(自动检测 模块加载时需要的别的模块) rmmod 用户空间工具, 加载模块到运行中的内核以及去除它们. #include module_init(init_functi ...

  8. 内联函数有什么优点?内联函数与宏定义的区别?

    内联函数的优点 内联函数比宏定义更加的安全,因为前者进行参数检查,而后者仅仅是简单地文本替换. 内联函数和宏定义的区别 宏定义是在预处理阶段进行的文本替换. 内联函数是在编译阶段进行的替换,优点是减少 ...

  9. 内联函数和宏定义的区别

    用内联取代宏: 1.内联函数在运行时可调试,而宏定义不可以; 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而宏定义则不会:  3.内联函数可以访问类的成员变量,宏定义则不能 ...

最新文章

  1. IPv6地址分类及表示方法
  2. ssh端口映射,本地转发
  3. json移除一个元素_leetcode:203.移除链表元素,听说用虚拟头节点会方便很多?
  4. sklearn自学指南(part48)--截断奇异值分解和潜在语义分析
  5. 如何查看文件夹里有几张图片_如何把几张图片合成一个pdf?图片合并为pdf的操作教程...
  6. [PAT乙级]1039 到底买不买
  7. CVPR 2019 | 腾讯AI:做好活体检测,模型重要,数据亦然
  8. vs2017编写模板类出现以下错误时:没有与参数列表匹配的构造函数……
  9. android编译终止,android - Android NDK-没有此类文件或目录编译终止-头文件导出问题 - 堆栈内存溢出...
  10. linux内核奇遇记之md源代码解读之六
  11. shiro框架实现权限管理
  12. 电子与电工技术实验——集成运算放大器的应用
  13. UltraISO制作U盘系统盘安装CentOS经验分享
  14. win7升级win10正式版_最新win7如何升级win10操作教程,你还在用win7吗?
  15. linux 分区表 修复工具,介绍一个 GPL 的分区表修复工具 TestDisk
  16. K.im团队与Kim Dotcom AMA直播回顾
  17. 为什要使用BindService?为了调用服务中的方法
  18. java日志,需要知道的几件事(commons-logging,log4j,slf4j,logback)
  19. 混合波束成形|基础:深入浅出5G,毫米波,大规模MIMO与波束赋形
  20. Gherkin语法详解之DataTable(三)

热门文章

  1. java并发编程实战wwj----------------------第一阶段--------------16-17-18-19-20
  2. Web3中文|构建Web3融资交易:股权和内部代币分配的比例
  3. VM15安装macOS一些问题,unlocker解锁后无mac选项,mac系统磁盘分区问题
  4. 微信里image 和 image2目录下的内容是什么东西?
  5. 光明大陆服务器等级在哪显示,《光明大陆》新版周五上线 等级直升系统详解备战萨达尔!...
  6. 数据库关系代数运算之连接
  7. POST和GET有什么区别?
  8. 机器学习之机器学习绪论-王而川-专题视频课程
  9. 用imu_tk和imu_utils标定imu
  10. 如何基于Agora Web SDK实现小程序互动连麦