什么是指针?
指针就是地址,int a;a是整形变量,而int* p=&a; (给指针p赋值是给p一个地址) 带*就代表是一个指针是int类型指针是存放int类型数据的指针,指针能够通过地址解引用获取到变量值,也能通过指针修改对应地址的值。指针更多的功能往下看我会一一讲解。
*号用于定义指针和解引用操作,当int a=10; int *p =&a,
就能通过*号通过地址找到存放的值如printf("%d",*p);屏幕会显示a变量中存放的值
字符指针
char a='A';
char *p=&a;//字符类型数据存放到字符指针,整形数据类型存放到整形指针中
printf("%c",*p); //屏幕会显示'A'
const char* ptr1="hello world" //ptr1会存放第一个字符'h'的地址,内容不能更改
const char* ptr2="hello world"//编译器不会再从新找一块空间存放"hello world",因为上一条指令已经给它开辟了空间,"hello world"是字符串常量,所以不会在开辟空间。
int main()
{
char arr1[]="hello world";
char arr2[]="hello world";
const char *arr3="hello world";
const char *arr4="hello world";
if(arr1==arr2)//地址比较
{
printf("YES");
}else
{
printf("NO");
}
if(arr3==arr4)
{
printf("YES");
}else
{
printf("NO");
}
}
输出结果为NO YES
字符串"hello world"定义在数组中是变量,所以即使两个数组中值一样也会在不同的地址空间存放相同值。
在指针初始化中是常量,常量无需在开辟空间(第一个常量"helloworld"已经在内存中开辟了空间,执行到第二个常量"hello world"时,编译器就不会在开辟一摸一样的常量,浪费空间 ,所以两个指针指向的地址是一样的),所以第一条结果为NO,第二条结果为YES。
void指针类型能够接收任何数据类型,类似于垃圾桶,但不能解引用使用。
二级指针
二级指针的作用?
二级指针是存放一级指针的地址
int a = 10;
int* pa = &a;
int **pb = &pa;
printf("%d\n",a);//输出10
printf("%d\n",*pa);//输出a的值
printf("%d\n",**pb);//间接输出a的值(*pb得到的是pa指向的地址,**pb找到的是pa指向地址的值)
指针数组
指针数组是指针还是数组?
答:是数组,是存放指针(地址)的数组
运行结果为10 20 30 40
数组指针
数组指针是指向数组的指针
#include <stdio.h>
//下列哪项接受参数是正确的?
void fun(int arr[])//YES 数组传参用数组接收没问题,其本质上在这里并不是数组而是指针
{
;
}
void fun(int arr[10]) //YES
{
;
}
void fun(int *arr) //YES 实参是地址,用指针接收没问题
{
;
}
void fun(int **arr) //NO 二级指针 接收一级指针
{
;
}
void test(int* arr2[10]) //YES
{
;
}
void test (int* p) //YES 数组名是首元素地址,数据类型是int* 用一级指针接收
{
;
}
int main() {
int arr1[10];
fun(arr1);
int* arr2[10];
test(arr2);
return 0;
}
二维数组数组名传参,不能使用一级或者二级指针接收,因为二维数组首元素的地址是行地址,要使用数组指针接收。
函数指针
函数指针是指向函数的指针
#include<stdio.h>
int Add(int x,int y)
{
return x+y;
}
int main()
{
//int *p(int, int)=Add; 写法错误,p会先和()结合,便不是指针。
int(*p)(int ,int)=Add;//Add==&Add
int k=(****p)(3,4);//p(3,4)==(*p)(3,4)==(n个* p)(3,4)
printf("%d\n",k);
return 0;
}
函数指针数组
存放函数指针的数组,格式:int(*p[4])(int ,int)
解释:数组有四个元素每个元素指向一个函数,每个函数参数是int int,返回值为int
制作一个简易计算器
#include<stdio.h>
int Add(int x,int y)
{
return x+y;
}
int Sub(int x,int y)
{
return x-y;
}
int Mul(int x,int y)
{
return x*y;
}
int Div(int x,int y)
{
return x/y;
}
void menu()
{
printf("*************************\n");
printf("*********1.Add***********\n");
printf("*********2.Sub***********\n");
printf("*********3.Mul***********\n");
printf("*********4.Div***********\n");
printf("*********0.退出游戏********\n");
printf("*************************\n");
}
int main()
{
int(*p[4])(int ,int)={0,Add,Sub,Mul,Div};
int input;
menu();
int x,y;
scanf("%d",&input);
do
{
scanf("%d",&input);
if(input>=1&&input<=4)
{
scanf("%d %d",&x,&y);
printf("%d",(p[input](x,y)));
}else if(input==0)
{
printf("退出游戏");
}else{
printf("输入有误");
}
}while(input);
return 0;
}
指向函数指针数组的指针
void(*(*ptr)[5])(int ,int)=&ptrr;
指针指向数组,数组5个元素每个元素都是函数指针
qsort的使用
头文件#include<stdlib.h>
#include<stdio.h>
#include<stdlib.h>
int cmp(const void* e1,const void* e2){
return (*(int*)e1-*(int*)e2);
}
int main()
{
int arr[10]={1,3,5,7,9,2,4,6,8,10};
qsort(arr,sizeof(arr)/sizeof(arr[0]),sizeof(arr[0]),cmp);
// 要排序的数组。 数组长度。 元素大小 比较函数
for(int i=0;i<10;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}
利用冒泡排序模拟实现qsort
#include<stdio.h>
#include<stdlib.h>
int cmp(const void* e1,const void* e2){
return (*(int*)e1-*(int*)e2);
}
void swap(void*arr1,void*arr2,int k)
{
int i=0;
for(i=0;i<k;i++)
{
char m=*((char*)arr1+i);
*((char*)arr1+i)=*((char*)arr2+i);
*((char*)arr2+i)=m;
}
}
void fun(void*arr,int sz,int k,int(*p)( void*, void*))
{
int i=0,j;
for(i=0;i<sz;i++)
{
for(j=0;j<sz-i-1;j++)
{
if(p((char*)arr+j*k,(char *)arr+(j+1)*k)>0)
{
swap((char*)arr+j*k,(char *)arr+(j+1)*k,k);
}
}
}
}
int main()
{
int arr[10]={1,3,5,7,9,2,4,6,8,10};
// qsort(arr,sizeof(arr)/sizeof(arr[0]),sizeof(arr[0]),cmp);
// 要排序的数组。 数组长度。 元素大小 比较函数
fun(arr,sizeof(arr)/sizeof(arr[0]),sizeof(arr[0]),cmp);
for(int i=0;i<10;i++)
{
printf("%d\n",arr[i]);
}
return 0;
}