指针专题
距离上一次详谈数组的博客已经有俩三个周了啊,这一次我们就来讲讲最令大家头疼的指针吧!
今天只要讲的就是一下的内容:
字符指针
字符指针使用char * 来定义,一般使用:
#include <stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
* pc = 'W';
printf("%c",ch);
return 0;
}
那么,我们不免会见到这样的代码:
#include <stdio.h>
int main()
{
char *p = "hello word!";
printf("%s",p);
return 0;
}
看完这个代码之后,是不是会产生一种错觉是在指针p中放着“hello word!”,其实不是,而是把“hello word!”的首地址放到p中,是因为,“hello word!”位于字符常量区,所以该p指针指示指向该字符串的首地址。
为了使大家更清楚一点,我们再来看一个代码:
#include <stdio.h>
int main()
{
char str1[] = "hello word!";
char str2[] = "hello word!";
char* str3 = "hello word!";
char* str4 = "hello word!";
if (str1 == str2) {
printf("str1 and str2 are same address.\n");
}
else {
printf("str1 and str2 are not same address.\n");
}
if (str3 == str4) {
printf("str3 and str4 are same address.\n");
}
else {
printf("str3 and str4 are not same address.\n");
}
return 0;
}
运行的最后的结果为:
于是,我们可以看得出来,用数组存储的相同的内容,其地址是不一样的,但是用指针存储的地址就是一样的也就是说,指针存储的是在字符常量区里面放置的。
数组指针、指针数组
首先,我们要明确的知道,数组指针是指针,不是数组。
那么,我们来区别一下数组指针和指针数组:
int* p[10];
int(*p)[10];
第一个是指针数组,第二个数组指针,我们如何判断一个变量是数组指针还是指针数组呢?我们就看变量p是先和那个操作符结合,先和*的话那他就是指针,先和【】就是数组。
数组指针顾名思义就是指向数组的指针,也就是说指针中放的是数组的地址。
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
int(*p)[10] = &arr;
int i = 0;
for (; i < 10; i++) {
printf("%d ", (*p)[i]);
}
return 0;
}
这种使用数组指针的写法不推荐大家使用,因为很少回去这样写代码。
那数组指针到底怎么用呢?看代码:
#include <stdio.h>
void printf_arr1(int arr[][5], int x, int y)
{
printf("printf_arr1 : ");
int i = 0;
for (; i < x; i++) {
int j = 0;
for (; j < y; j++) {
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
void printf_arr2(int (*arr)[5], int x, int y)
{
printf("printf_arr2 : ");
int i = 0;
for (; i < x; i++) {
int j = 0;
for (; j < y; j++) {
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
int main()
{
int arr[2][5] = { 1,2,3,4,5,6,7,8,9,0 };
printf_arr1(arr, 2, 5);
printf_arr2(arr, 2, 5);
return 0;
}
我们可以看得出来这俩个函数的的区别就在于函数传参的变量的不一样,但是他们虽然样子看上去不一样,但是其实是一个东西,这就是我们接下来要讲的数组传参和指针传参。
数组传参和指针传参
一维数组传参
void text1(int arr[])
{}
void text2(int arr[10])
{}
void text3(int *arr)
{}
void text4(int *arr[20])
{}
void text5(int **arr)
{}
text4和text5传参的是一维指针数组
二维数组传参
void text1(int arr[][5])
{}
void text2(int arr[3][5])
{}
void text3(int (*arr)[5])
{}
void text4(int **arr)
{}
二维数组传参只能省略第一个【】中的数字,因为二维数组和不知道有多少行,但是必须知道一行有多少个元素。
一级指针传参
#include <stdio.h>
void first_point(int *p,int num)
{
int i = 0;
for (; i < num; i++) {
printf("%d ", *(p++));
}
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,0 };
int* p = arr;
int num = sizeof(arr) / sizeof(arr[0]);
first_point(p, num);
return 0;
}
二级指针传参
#include <stdio.h>
void second_point(int** p)
{
printf("%d ", **p);
}
int main()
{
int n = 10;
int* p = &n;
int** pp = &p;
second_point(pp);
second_point(&p);
return 0;
}
函数指针
我们都知道变量是在内存中开辟空间的,我们也知道在内存中有一块区域叫做代码区,那么我们写的代码是不是也有地址?我们的变量有地址、空间,那函数有没有呢?所以我们引进一个新的概念,叫做函数指针。
#include <stdio.h>
void address()
{}
int main()
{
printf("%p\n", address);
printf("%p\n", &address);
return 0;
}
我们看输出的俩个地址是一样的,也就是说函数是有他自己的储存空间和地址的。
函数指针数组
#include <stdio.h>
void a()
{
printf("a ");
}
void b()
{
printf("b ");
}
int main()
{
int(*p[3])() = { 0,a,b };
(*p[1])();
(*p[2])();
return 0;
}
这个就是函数指针数组,这个可以用来简化简单的重复的一些代码,方便我们提高代码的书写效率。
指向函数指针数组的指针
现在我们把复杂度再次提上一个高度:指向函数指针数组的指针是一个指针,指向一个数组,数组的元素都是函数指针。
#include <stdio.h>
void p_point(const char *p)
{
printf("%s\n", p);
}
int main()
{
void (*pfun)(const char*) = p_point;
void (*pfunArr[5])(const char* p);
pfunArr[0] = p_point;
void (*(*ppfunArr)[10])(const char*) = &pfunArr;
return 0;
}
回调函数
——什么是回调函数?
回调函数是一个通过函数指针调用的函数,看代码:
#include <stdio.h>
int int_cmp(const void* p1, const void* p2)
{
return (*(int*)p1 - *(int*)p2);
}
int main()
{
int arr[] = { 1,2,5,3,0,8,9,6,4,5,7 };
int i = 0;
qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
for (; i < sizeof(arr) / sizeof(arr[0]); i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
此代码中的int_cmp函数就是回调函数,回调函数是在特定的事件或条件发生时由另一方调用的。
上一篇: 常见几种数据库备份与恢复
下一篇: DB2数据库基本特性和概念简介