cJSON的内容真的不多,毕竟我们只是去查看而不是自己去写,所以总归看得还是很快的。我们毕竟不是自己做项目,只是针对前人做的东西进行理解,学习别人的编程思维。因为cJSON毕竟使用c写的,语法涉及的也并不多,无非就是指针的来回应用,这也说明指针的强大,指针也正是c语言的精髓。然后针对个人的阅读,对cJSON涉及到的知识而自己又不太熟悉的地方做一些总结。
const关键词的应用
没错,我就想来讲讲这个关键词,这真的是一个很简单的关键词了。const的意思定义的变量的值不能改变。关于const修饰的词的含义,翻书或者百度一大堆。我大概的举几个例子:
const int c; //错误,没有初始化
const int c = 0; //记住,const对象必须初始化
//从右往左阅读
int value = 17;
const int* ptr = &value; //ptr所指向的内容不能变
int* const ptr = &value; //ptr不能变
const int* const ptr = &value; //都不能变
//修饰函数返回值
//可能很多初学者和我一样,认为const放在最前面是修饰函数的...
const int fun(int a); //防止函数返回值被修改
//关于在c++中的使用
//const修饰类成员函数(放在成员函数的后面),防止类成员函数中除了static成员之外的其他成员被修改
//类的成员变量可以分为静态的和非静态的,如果const修饰的是静态的成员变量,可以在构造函数中对该变量进行初始化;如果const修饰的是静态的成员变量,则需要在类外对该变量进行初始化
关于类修饰成员函数或成员变量的我就不举例了。
这里我主要想表达的是,const用作修饰函数参数的问题,不知道大家有没有和我一样,因为我也没做过什么项目,所以我平常自己敲代码,做算法题的时候,几乎不用const限定符。因为也用不到嘛。而我发现cJSON里面却用的特别多如下图:
当然其实修饰函数返回值也是比较多的:
基本上就这俩情况用的比较多,那我们就稍稍的做个总结:
1 const修饰函数参数,一般修饰的是引用或者指针传参的情况,用的比较多,可以防止意外地改动实参的值,起到对实参的保护作用
2 const修饰函数返回值,可以防止返回值被修改(其实我还没弄懂这个有哪些具体的好处)
static关键词的应用
在c/c++中,static可以修饰变量、修饰函数(附个链接:http://c.biancheng.net/view/301.html),用static修饰的函数,限定在本源码文件中,不能被本源码文件以外的代码文件调用。而普通的函数,默认是extern的,也就是说它可以被其它代码文件调用。
好处就是其他文件中可以定义相同名字的函数,不会发生冲突。
函数指针
指针这东西真是让人又爱又恨,我看cJSON的时候又碰到这个鬼函数指针了,这个用的少的话,真的是看了忘,忘了又看,重复着,就感觉很陌生。。。
关于定义和使用方法,百度搜索会发现有很多,我就懒的写了(附个链接:http://c.biancheng.net/view/228.html),我大概的讲一下语法规范,讲讲指针函数和函数指针的区别.
//指针函数,这里要强调一下,()的优先级高于*,这里返回的是指针类型的函数
int *fun(int a, int b){}
//函数指针,指向函数的指针
//重点,函数指针是一个指针
//定义一个函数指针有三种方式
//1 不常用
typedef int FUN(int a, int b); //FUN函数类型
FUN *p = nullptr; //函数指针变量
p = fun; //p指向fun函数
p(1, 2); //正确
//2常用
//PFUN函数指针类型
typedef int (*PFUN)(int a, int b); //(*FUN)一定要加括号,这还是优先级的问题
PFUN p = fun; //函数指针变量
p(1, 2);
//3常用
int (*p)(int a, int b) = fun;
p(1, 2);
这里我举个例子吧,讲讲大名鼎鼎的快速排序sort()函数。
Sort函数包含在头文件为algorithm的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的。但是我还是想把sort()函数源码拿出来看看。
Sort函数有三个参数:第一个是要排序的数组的起始地址。第二个是结束的地址(最后一位要排序的地址的下一地址)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
没错这里的第三个参数的排序方法就是以函数指针的形式传入的。我在网上找了会,的确没找到源代码。这里我手写一份类似的排序方法,也就是用到回调函数的排序,就用c语言写吧。
void mySort(int *start, int *end, _Bool (*cmp)(int, int))
{
if (start >= end)
return;
int *i = start;
int *j = end;
int tmp = *start;
while (i < j)
{
while (cmp(*j, tmp) && i < j)
j--;
if (i < j)
{
*i = *j;
i++;
}
while (!cmp(*i, tmp) && i < j)
i++;
if (i < j)
{
*j = *i;
j--;
}
}
*i = tmp;
mySort(start, i - 1, cmp);
mySort(i + 1, end, cmp);
}
我没有写注释了,学过快排看懂没问题吧?没学过的还不快去学学?!另外这里我给个test.
//从小到大排序
_Bool cmp1(int a, int b)
{
return a >= b;
}
//从大到小排序
_Bool cmp2(int a, int b)
{
return a < b;
}
int main(void)
{
int arr[] = {2,1,5,8,9,7,5,1,6,4};
mySort(arr, arr + sizeof(arr) / sizeof(int) - 1, cmp1);
for (int i = 0; i < sizeof(arr) / sizeof(int); i++)
{
printf("%d ", arr[i]);
}
system("pause");
return 0;
}
到这里,回调函数的优势就显现出来了,可以少写很多代码,同一个函数可以调用不同的函数(回调函数),来实现从小到大或则从大到小排序。
今天就讲到这。