技术总结:
在进行软件开发的时候,技术迭代更新速度极快。而想要快速掌握这些技术,需要非常扎实的基础才行。那么,现在我们就来谈一谈程序员的开端——C语言。C语言中,最困难的两大知识点就当属指针与函数。指针的困难点倒不是在于它本身,困难的是指针与其他数据类型相结合,其形成的组合种类较多,最后导致指针难以理解。下面,我们就先从指针说起。
指针的基础:
1.指针的概念:
指针实际上就是地址。指针是在计算机自动在内存中分配的一块空间,该空间用来存储地址(该空间大小由操作系统来决定,64位操作系统,需要用64位,也就是8字节空间来保存地址),而存储的这个地址,是该指针所指向的那块空间的首地址。int *p = &A;
我们想要通过指针取到A空间中的数据,可以使用*p来取(注意:*p表示的是A这块空间,而不是A空间中的数据,就像int A; 变量名A,表示的是A这个空间)。而A空间的首地址可以由p或&A来表示。
这样,指针的本质就讲完了,是不是很就简单?但这只是开始。
指针的组合:
- 指针与数组的组合:
指针与数组的组合有很多,如:数组指针,多级指针,函数指针,结构体指针。数组指针中,比较难理解的就是,指针与二维数组的组合。想要弄清楚指针与二维数组的组合,我们先来看一维数组。一维数组的。。。。。。
函数的基础:
1.函数的概念:
函数实际上就是程序的跳转,即先将当前程序的状态保存在栈中,然后跳转到相对应的函数内,依次执行函数内的程序指令。当函数执行完后,函数被释放,然后恢复之前保存在栈中的程序状态,再接着往下执行程序。
我们之所以需要函数,主要还是因为我们不可能将一个项目中的所有程序指令都写在main函数中去,一旦项目复杂的话,对程序的修改和调试将是一场灾难。如下图:
所以在做项目的时候,我们保证项目高内聚,低耦合。这个时候就需要函数来将代码封装起来了。我们常常使用的函数都是封装起来的,而使用函数的难点就在于函数的参数如何填写和判断函数的返回值是什么。
1.函数的形参与返回值:
函数的格式: 返回值类型 函数名字(形参)
{
函数体;
return xx;
}
一维数组作为函数的形参:
int arr[5]={1,2,3,4,5};
函数格式:
1*> test(int *p)
2*> test(int p[])
3*> test(int p[5])
函数填写:test(arr);(arr是数组名,也是数组的首地址)
(注意:如果此时是test(int p),则因为形参为int类型而不是指针类型,所以不能写成test(arr); 我们可以填写成test(arr[1]),arr数组中的每一个元素都为int类型。这样可以,将arr数组中的第一个元素传入到tset函数中去。)
数组作为函数的返回值:
int *test(void)
{
int arr[5];
return arr;(返回的仍然是数组的首地址,即数组名)
}
(注意:在函数内定义的数组,在函数结束后,数组会被释放,如果将此数组作为返回值返回给main函数的话,由于数组已经被释放了,所以数组无法被找到,会发生错误。解决办法:1.堆 malloc 2.静态变量 static)
二维数组作为函数的形参:
int arr[2][3]={1,2,3,4,5,6};
函数格式:
1*> test(int (*p)[3])
2*> test(int p[][3])
3*> test(int p[2][3])
函数填写:test(arr);(arr是数组名,也是数组的首地址)
指针作为函数的形参:
int *p;
函数格式:
test(int *x)(一级指针)
test(int **x)(二级指针)
函数填写:test(p);
test(&p);
指针作为返回值:
int *test(void){
int *p;
return p;
} 返回一个一级指针
int **test(void){
int *p;
return &p;
} 返回一个二级指针
函数作为一个函数的参数: (回调函数)
void test(int a){}
函数格式:
int xx(void (*p)(int))
函数填写:xx(test)(test是另外一个函数的名字)
我们知道,函数的名字就是函数的入口也就是函数的首地址。所以,由此可知函数指针的本质就是用来保存函数的首地址(即函数名)
void (*p)(int)实际上就是,void (*)(int) p(定义了一个指针,其中void (*)(int)为指针类型,p为指针),例如:void (*)(int) p = test;其中p就表示为一个指向函数test()的函数指针。前面我们说过,指针实际上就是地址,也就是说void (*)(int) p是一个用来保存函数text函数首地址的指针(即用来保存test函数名字)。但是void (*)(int) p这种格式,C语言标准不认可,我们需要写成void (*p)(int)这种格式。
函数作为函数的返回值:
void test(int a){}
void (*xx(int x))(int){
void (*p)(int);
return p;
}
void (*xx(int x))(int)实际上就是,void (*)(int) xx(int x)
xx(int x)是一个函数,其返回值为void(*)(int)函数指针类型,即其返回值是一个指向其他函数的指针。注意:xx(int x)是一个函数,而不是一个用来保存地址的指针,所以此时void (*)(int)就为函数的返回值,而不是指针的指针类型。
结构体作为函数的形参:
struct xx{
int a;
short b;
};
函数格式:test(struct xx yy)
函数填写:
struct xx sx={10,20};
test(sx);
结构体作为函数的返回值:
struct xx test(void) {
struc xx sx;
return sx;
}
好了,到目前为止,函数基本的使用我们已经知道了。但是编程还是需要大量的实践与理论学习,多看看经典的计算机书籍,会让我们对编程的理解更加深入。