接下来记录的是C语言的函数部分,宏定义,结构体的知识。相对重要的部分,重点理解。
函数:
函数是一个完成特定功能的代码模块,其程序代码独立,通常要求有返回值,也可以是空值。
一般形式:
<函数类型> <函数名称> (<形式参数>)
{
语句序列:
return (<表达式>);
}
前面基础的部分在之前的c++以及其他语言基础下,理解较为容易,省略记录。
函数的参数传递:
函数之间的参数传递方式:
全局变量 复制传递的方式 地址传递的方式
全局变量:
全局变量就是在函数体外说明的变量,他在程序中的每个函数都是可见的
全局变量一旦定义在程序的任何地方都可见,函数的调用的位置不同,程序的结果可能受到影响,不建议使用。
复制传递方式:
调用函数将实参传递给被调用函数,被调用函数将创建相同类型的形参并用传来的实参初始化。
形参是新开辟的存储空间,因此在函数中改变形参的值,不会影响到实参。
地址传递方式:
按地址传递,实参为变量的,而形参为同类型的指针。
被调用函数的对形参的操作将直接改变实参的值。
数组在函数中的传递与上述类似,类比可以了解。
指针函数
指针函数是指一个函数的返回值为地址量的函数。
一般形式在 函数类型后加上了*。
递归函数:
递归函数是指在一个函数的函数体中直接或者间接的调用到了函数自身。
分两个阶段:
递归阶段:从原问题出发,按递推公式从未知到已知,最后达到递归的终止条件。
回归阶段:按递归终止条件求出结果并逐步带入递归公式,回归到原问题求解。
这部分在数据结构中也非常重要,应该理解清楚这个具体过程。
函数指针,函数指针数组:
在C语言中,函数指针是一种特殊的指针类型,它指向一个函数的入口地dd数指针可以让我们以函数为参数传递给其他函数,或者将函数赋值给 变量,以便程序中动态的使用函数。
注意:函数指针用来存放函数的地址。函数名代表的是函数的入口地址。
1.定义:
int (*functionPtr)(int, int);
2.初始化函数指针:
Int add(int a , int b )
{
return a+b;
}
int (*functionPtr)(int , int ) = add ; //初始化函数指针指向add函数;
3.通过函数指针调用函数。
int result = functionPtr( 3 , 4 ); //调用add函数
4,将函数指针作为参数。
void performoperation( int (* operation)(int int ),int a ,int b )
{
int result = opreation (a,b);printf ("result : %d \n",result);
}
performoperation(functionPtr , 3 ,4);
函数指针数组是一个保存若干个函数名的数组。
<数据类型>(*<函数指针数组名称>)<[大小]> (<参数说明列表>)
int square(int x) { return x * x; }
int identity(int x) { return x; }
int (*functions[])(int) = {square, identity};
其他的同普通的函数指针。
使用typedef简化声明:
使用typedef为函数指针创建一个新的别名,简化声明。
typedef int (*funptr) ( int )( int );
funptr functionptr; //使用typedef简化函数指针的声明。
函数指针和结构体:
将函数指针作为结构体的成员,实现类似面向对象的行为;
typedef struct
{
int (* operation)( int )( int )
}operation;
operation addop = {add};
int result = addop.operation( 3, 4);
回调函数:
使用函数指针实现回调机制,即一个函数作为参数传递给另一个函数,并在后者内部被调用。
void execute(int a, int b, int (*callback)(int, int))
{
printf("Result of operation: %d\n", callback(a, b));
}
execute(5, 3, add);
宏定义:
基本语法:
#define indentifier repalcement-text
分为有参宏和无参宏
1/无参宏:(最简单的宏定义,没有参数,只是简单的文本替换)
#define PI 3.14159
2/有参宏:(宏可以带参数,类似于一个没有函数体的函数)
#define square(X) ( ( x ) * ( x ) )
3/字符串化运算符#:
#define STRINGIZE(x) #x
STRINGIZE (hello world); //将被替换为“hello world”
4/连接运算符##
#define CONCAT(x,y) x ## y
CONCAT(a,b);
5/条件编译
#ifdef 用来检查一个宏是否被定义。如果宏已经被定义,编译器会包含#ifdef和#endif 之间的代码。
#ifdef identifier
/* 条件为真时包含的代码 */
#endif
#ifndef 与ifdef相反,他检查一个宏是否没有被定义,如果没有被定义,将会包含#ifndef
和#endif之间的代码。
#else: #elif (Else if):
6./宏的展开
宏在预处理阶段展开,替换他们在代码中所有出现的地方。
7/递归宏
宏可以递归的调用自身,但使用要小心避免栈溢出。
限制:宏没有类型检查。只是简单的文本替换。
注意:使用宏时要注意宏 的定义,避免重复执行的部分。
#undef 对作用域的取消。
结构体:
C语言中结构体是一种强大的数据类型,它允许你将不同类型的数据项组合成一个单一的实体,结构体可以用于创建更复杂的数据结构,例如链表,树和图形。
定义结构体:
struct mystruct{
int id;
char name[34];
float value;
}
声明结构体变量以及初始化:
struct mystruct val;
struct mystruct val2 = {10,"name",1.234};
匿名结构体:
匿名结构体是指没有显式名称的结构体,通常与typedef结合使用。
typedef struct {
int id;
char name[50];
float value;
} Data;
结构体的嵌套:
这里用一个具体的程序列子来说明。
#include <stdio.h>
#include <stdlib.h>
void main()
{
struct data {
int year;
int month;
int day;
};
struct
{
int num;
char name[20];
struct data birthday;
}boy1,boy2;
printf("please enter your birther!(year,month,day)");
scanf("%d %d %d",&boy1.birthday.year,&boy1.birthday.month,&boy1.birthday.day);
}
结构体数组:
结构体数组是将结构体变量按照数组的形式组织起来,这样就可以创建具有多个相同类型的结构体实例,其他部分初始化,引用,遍历与结构体相类似,不过分记录。
结构体作为函数参数:
将结构体变量作为参数传递给函数。
void display (struct mystruct s)
{
printf("ID:,%d \n",s,id);
}
结构体指针
与结构体的大部分可以类似相同。
注意引用结构体成员用"->",结构体指针也可以作为参数传递给函数,允许函数访问或修改结构体变量。
结构体与函数返回。
函数可以返回结构体类型的值。可以理解为定义自己写的结构体类型的函数,返回值类型也是结构体类型的。
其他注意的还有可以作为联合体(union)的成员,还可以包含枚举类型。
结构体还有很多地方的用途,等之后的学习中遇到再进行记录。