文章目录
指针的主题,我们在初级阶段的《指针》章节已经接触过了,我们知道了指针的概念:
- 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
- 指针的大小是固定的4/8个字节(32位平台/64位平台)。
- 指针是有类型,指针的类型决定了指针的±整数的步长,指针解引用操作的时候的权限。
- 指针的运算。
1.字符指针
在指针的类型中我们知道有一种指针类型为字符指针char*;
一种使用“变量指针”
int main()
{
char ch = 'w';
char *pc = &ch;
*pc = 'w';
return 0;
}
``
** ”常量指针“**
```c
int main()
{
const char* pstr = "hello bit.";//这里是把一个字符串放到pstr指针变量里了吗?
printf("%s\n", pstr);
return 0;
}
“hello bit”是一个常量,地址在常量区,不在栈区,所以不可以改变,而变量指针是把一个常量赋值到一个变量中,再把变量地址赋给指针变量。
那就有可这样的面试题:
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char *str3 = "hello bit.";
const char *str4 = "hello bit.";
if(str1 ==str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if(str3 ==str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
注意:在栈区一定是新占一个空间;所以每个变量地址不同;
str3和str4是常量指针,所以二者存的都是常量区的“hello bit”的地址;
2.指针数组
在《指针》章节我们也学习了指针数组,指针数组是存放指针的数组。
例题
使用指针数组来模拟二维数组
3.数组指针
3.1 数组指针的定义
数组指针是指针?还是数组?
答案是:指针。
下面代码哪个是数组指针?
int *p1[10];
int (*p2)[10];
//p1, p2分别是什么?
p1是指针数组,而p2是数组指针;可以发现:数组指针比指针数组多加了一个()。
3.2 &数组名VS数组名
数组名和&数组名的区别:
指针类型不同:
arr:int *pa 指针变量
&arr:int(*pa)[10] 数组指针;
两者数值相同但是两者加一的数值加的比一样;
3.3 数组指针的使用
3.3.1示例一
3.3.2示例二,二维数组
4. 数组参数、指针参数
4.1 一维数组传参
4.2 二维数组传参
终结:
数组传参都有数组型和指针型。
4.3 一级指针传参
思考:
当一个函数的参数部分为一级指针的时候,函数能接收什么参数?
4.4 二级指针传参
#include <stdio.h>
void test(int** ptr)
{
printf("num = %d\n", **ptr);
}
int main()
{
int n = 10;
int*p = &n;
int **pp = &p;
test(pp);
test(&p);
return 0;
}
思考:
当函数的参数为二级指针的时候,可以接收什么参数?
5. 函数指针
#include <stdio.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
return 0;
}
由此可以看出函数名字是函数的地址;
函数指针如何写
举例:
**但是使用时函数指针不需要用”*“;
因为:函数本来就用的是地址;
5.1例题
5.1.1
//代码1
(*(void (*)())0)();
5.1.2
//代码2
void (*signal(int , void(*)(int)))(int);
6. 函数指针数组
把函数的地址存到一个数组中,那这个数组就叫函数指针数组。
//例子:
int(*pa[10])(int,int)
用途
示例:
计算器
1.使用函数数组的方法:
#include<stdio.h>
int add(int a,int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
return a / b;
}
void mune()
{
printf("************************\n");
printf("*******1.add,2,sub******\n");
printf("*******3.mul,4.div******\n");
printf("*******0.退出***********\n");
}
int main()
{
int a = 0, b = 0;
int (*pa[5])(int, int) = { 0,add,sub,mul,div };
int input;
int ret = 0;
do
{
mune();
scanf("%d", &input);
if (input>=1&&input<=4)
{
printf("输入操作数: ");
scanf("%d %d", &a, &b);
ret = pa[input](a,b);
}
else if(input==0)
{
printf("退出");
}
else
{
printf("输入错误");
}
printf("ret=%d\n", ret);
} while (input);
return 0;
}
2.使用分支语句的方法:
7. 指向函数指针数组的指针
指向函数指针数组的指针是一个指针,指针指向一个数组,数组元素都是函数指针;
加指针就加一个()和
加数组就在名字后加【】*
8.回调函数
这里使用上面的代码进行解释;
使用回调函数的方法;
介绍qsort函数
该函数是一个排序函数;
根据前面的知识我们知道冒泡法,等排序法;
出现qsport函数的原因:
对于冒泡法排序的类型是固定的,大大影响了代码的效率;
qsort的定义
注意:qsort的底层算法是快速算法;
举例
1.整形排序
对于正常情况下qsort是将排序后是以升序来排列;
如果想要呈现降序:可以把p1和p2的位互换;
2.字符型排序
3.结构体排序
struct Ps
{
char name[20];
int age;
};
int cmp_stu_by_name(const void * p1, const void* p2)
{
return strcmp(((struct Ps*)p1)->name, ((struct Ps*)p2)->name);
}
void test()
{
struct Ps arr[] = { {"zhangsan",30},{"lisi",25},{"wangwu",50} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
printf("%s %s %s", arr->name, (arr + 1)->name, (arr + 2)->name);
}
int main()
{
test();
return 0;
}
使用冒泡法模拟可以排序任何类型序列的冒泡法;
功能和psort相同;
int cmp(const void* p1, const void* p2)
{
return *((int*)p1) - *((int*)p2);
}
void Swap(char* buf1, char* buf2, int width)
{
int i = 0 ;
for (i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void buble_sort(void* base, int num, int width, int(*cmp)(const void*p1,const void*p2))//size_t是无符号整形
{
size_t i = 0;
for (i = 0; i < num-1; i++)
{
int flag = 1;
size_t j = 0;
for (j = 0; j < num - 1 - i; j++)
{
if (cmp((char*)base+j*width,(char*)base+(j+1)*width)>0)
{
flag = 0;
Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
if (flag == 1)
{
break;
}
}
}
void test()
{
int s[] = { 3,1,2,4,5,6,7,8,9,10 };
int sz = sizeof(s) / sizeof(s[0]);
//使用冒泡法模拟一个可以随意选择类型的冒泡法(通用冒泡法);
buble_sort(s, sz, sizeof(s[0]), cmp);
}
int main()
{
test();
return 0;
}