指针进阶(C语言)
指针进阶
头文件
#include<stdio.h
#include<stdlib.h
#include<string.h
字符指针
int main()
{
//字符指针
char arr1[]="abcdef";
char arr2[]="abcdef";
char* p1="abcdef";
char* p2="abcdef";
if (arr1==arr2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
if (p1==p2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
printf("arr1:%p\n",arr1);
printf("arr2:%p\n",arr2);
printf("p1:%p\n",p1);
printf("p2:%p\n",p2);
return 0;
}
指针数组
int main()
{
int arr1[]={1,2,3,4,5};
int arr2[]={2,3,4,5,6};
int arr3[]={3,4,5,6,7};
int* parr[]={arr1,arr2,arr3};//指针数组-数组-存放指针的数组
int i = 0;
for (i=0;i<3;i++)
{
int j=0;
for (j=0;j<5;j++)
{
printf("%d ",*(parr[i]+j));
}
printf("\n");
}
return 0;
}
数组指针
int main()
{
int arr[5]={1,2,3,4,5};
int (*p)[5]=&arr;//数组指针-指针-数组的地址要存起来
return 0;
}
int main()
{
char* arr[5];
char* (*p)[5]=&arr;
return 0;
}
int main()
{
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int *p=arr;//arr[i]==*(arr+i)==*(p+i)==p[i]
int i=0;
for(i=0;i<10;i++)
{
printf("%d ",*(p+i));
}
// int (*p)[10]=&arr;
// int i=0;
// for(i=0;i<10;i++)
// {
// printf("%d ",(*p)[i]);
// }
// for(i=0;i<10;i++)
// {
// printf("%d ",*(*p+i));//*p==arr
// }
return 0;
}
数组参数,指针参数
//参数是数组的形式
void print1(int arr[3][5],int x,int y)
{
int i=0;
int j=0;
for (i=0;i<x;i++)
{
for (j=0;j<y;j++)
{
printf("%d ",arr[i][j]);
}
printf("\n");
}
}
//参数是指针的形式
void print2(int(*p)[5],int x,int y)
{
int i=0;
for(i=0;i<x;i++)
{
int j=0;
for(j=0;j<y;j++)
{
//printf("%d ",p[i][j]);
//printf("%d ",*(p[i]+j));
printf("%d ",*(*(p+i)+j));
//printf("%d ",(*(p+i))[j]);
}
printf("\n");
}
}
二维数组传参
int main()
{
int arr[3][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};
print1(arr,3,5);//arr-数组名-数组名就是首元素地址
print2(arr,3,5);//
return 0;
}
void test(int arr[3][5])
{}
void test1(int arr[][5])//可以省略行
{}
// void test2(int arr[3][])//err 不可以省略列
// {}
// void test3(int *arr)//err
// {}
// void test4(int **arr)//err
// {}
void test5(int (*arr)[5])
{}
int main()
{
int arr[3][5]={0};
// test(arr);//二维数组传参
// test1(arr);
// test2(arr);
// test3(arr);
// test4(arr);
test5(arr);
return 0;
}
void test1(int** p)
{}
int main()
{
int *ptr;
test1(&ptr);
int **pp=&ptr;
test1(pp);
int* arr[10];
test1(arr);
return 0;
}
函数指针
//数组指针——是指向数组的指针
//函数指针——是指向函数的指针——存放函数地址的指针
int Add(int x,int y)
{
int z=0;
z=x+y;
return z;
}
int main()
{
int a=10;
int b=20;
// int arr[10]={0};
// int (*p)[10]=&arr;
//printf("%d\n",Add(a,b));
//&arr;
//arr;
//&函数名 和 函数名 都是函数的地址
/*
printf("%p\n",&Add);
printf("%p\n",Add);
*/
int (*pa)(int,int) = Add;
printf("%d\n",(*pa)(2,3));
return 0;
}
void Print(char* str)
{
printf("%s\n",str);
}
int main()
{
void (*p)(char*) = Print;
(*p)("hello bite");
return 0;
}
// 代码一
// (*(void(*)())0)();
// void(*)()-函数指针类型
// 把0强制类型转换成void(*)()函数指针类型-0就是一个函数地址
// 调用0地址处的该函数
// 代码二
// void (*singal(int ,void(*)(int)))(int);
// signal是一个函数声明
// signal第一个参数整形,第二个参数是函数指针类型,该函数指针指向的函数的参数是int,返回类型是void
// signal函数返回类型-函数指针-void(* singal(int,void(*)(int)) )(int)
// 简化
// typedef void(*pfun_t)(int);
// pfun_t signal(int,pfun_t);
// typedef unsigned int unit;
int Add(int x,int y)
{
int z=0;
z=x+y;
return z;
}
int main()
{
int a=10;
int b=20;
int (*pa)(int,int) = Add;
printf("%d\n",pa(2,3));
printf("%d\n",Add(2,3));
printf("%d\n",(*pa)(2,3));//*是摆设
// printf("%d\n",(**pa)(2,3));
// printf("%d\n",(***pa)(2,3));没必要
return 0;
}
函数指针数组
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;
}
int main()
{
//指针数组
int* arr[5];
//需要一个数组可以存放四个函数的地址 - 函数指针的数组
//int (*pa)(int,int) = Add;//Sub/Mul/Div
int (*parr[4])(int,int) = {Add,Sub,Mul,Div};//函数指针的数组
int i = 0;
for (i=0;i<4;i++)
{
printf("%d\n",parr[i](2,3));
}
return 0;
}
函数指针数组的用途:转移表
void menu()
{
printf("*****************\n");
printf("** 1.add 2.sub**\n");
printf("** 3.mul 4.div**\n");
printf("** 5.Xor 0.exit**\n");
printf("*****************\n");
}
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;
}
int Xor(int x,int y)
{
return x^y;
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
//转移表
int (*pfArr[])(int,int)={0,Add,Sub,Mul,Div,Xor};
do
{
menu();
printf("请选择:");
scanf("%d",&input);
if(input = 1 && input <=5)
{
printf("请输入两个操作数:");
scanf("%d%d",&x,&y);
int ret = pfArr[input](x,y);
printf("%d\n",ret);
}
else if(input == 0)
{
printf("退出\n");
}
else
{
printf("选择错误\n");
}
}while(input);
return 0;
}
回调函数
void Calc(int (*pf)(int,int))
{
int x = 0;
int y = 0;
printf("请输入两个操作数:");
scanf("%d%d",&x,&y);
printf("%d\n",pf(x,y));
}
int main()
{
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d",&input);
switch (input)
{
case 1:
Calc(Add);
break;
case 2:
Calc(Sub);
break;
case 3:
Calc(Mul);
break;
case 4:
Calc(Div);
break;
case 0:
printf("退出\n");
break;
default:
printf("选择错误\n");
break;
}
}while(input);
return 0;
}
//回调函数2
void print(char* str)
{
printf("hehe:%s",str);
}
void test( void(*p)(char*) )
{
printf("test\n");
p("bit");
}
int main()
{
test(print);
return 0;
}
指向函数指针数组的指针
int Add(int x,int y)
{
return x+y;
}
int main()
{
int arr[10]={0};
int (*p)[10]=&arr;//取出数组的地址
int (*pfArr[4])(int,int);//pfArr是一个数组-函数指针数组
//ppfArr是一个指向[函数指针数组]的指针
int (*(*ppfArr)[4])(int,int) = &pfArr;
//
//ppfArr是一个数组指针,指针指向的数组有四个元素
//指向的数组的每个元素的类型是一个函数指针int(*)(int,int)
//
return 0;
}
冒泡排序
void bubble_sort(int arr[],int sz) //整形的冒泡排序
{
int i = 0;
for (i=0;i<sz-1;i++)
{
int j=0;
for (j=0;j<sz-1-i;j++)
{
if (arr[j]arr[j+1])
{
int tmp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = tmp;
}
}
}
}
// void qsort(void *base, size_t nmemb, size_t size,
// int (*compar)(const void *a, const void *b));
//base:指向待排序数组的第一个元素的指针。
//nmemb:数组中元素的数量。sz
//size:每个元素的大小(以字节为单位)。width
//compar:用于比较两个元素的函数指针,比较两个元素的所用函数的地址-这个函数使用者自己实现函数指针的两个参数是:带比较的两个元素的地址。
int cmp_int(const void* a,const void* b)
{
//比较两个整形值
return (*(int*)a - *(int*)b);;
}
void test1()
{
int arr[10]={9,8,7,6,5,4,3,2,1,0};
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,sz,sizeof(arr[0]),cmp_int);
int i = 0;
for (i=0;i<sz;i++)
{
printf("%d ",arr[i]);
}
}
int cmp_float(const void*a,const void* b)
{
return *(float*)a - *(float*)b;
}
void test2()
{
float f[]={9.0,8.0,7.0,6.0,5.0,4.0,3.0};
int sz = sizeof(f) / sizeof(f[0]);
qsort(f,sz,sizeof(f[0]),cmp_float);
int j = 0;
for (j=0;j<sz;j++)
{
printf("%f ",f[j]);
}
}
struct Stu
{
char name[20];
int age;
};
int cmp_stu_by_age(const void* a,const void* b)
{
return ((struct Stu*)a)-age - ((struct Stu*)b)-age;
}
int cmp_stu_by_name(const void* a,const void* b)
{
//比较字符串用strcmp
return strcmp(((struct Stu*)a)-name,((struct Stu*)b)-name);
}
void test3()
{
struct Stu s[3]={{"zhangsan",20},{"lisi",30},{"wangwu",10}};
int sz = sizeof(s) / sizeof(s[0]);
//qsort(s,sz,sizeof(s[0]),cmp_stu_by_age);
qsort(s,sz,sizeof(s[0]),cmp_stu_by_name);
int k = 0;
for (k=0;k<sz;k++)
{
printf("%d " ,s[k].age);
//printf("%s " ,s[k].name);
}
}
// 实现bubble_sort函数的程序员,他是否知道未来排序的数据类型-不知道
// 那程序员也不知道,带比较的两个元素的类型
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 bubble_sort(void* base,int sz,int width,int(*cmp)(void*a,void*b))
{
int i = 0;
//趟数
for (i=0;i<sz-1;i++)
{
//每一趟比较的对数
int j = 0;
for(j=0;j<sz-1-i;j++)
{
//两个元素比较
if(cmp((char*)base+j*width,(char*)base+(j+1)*width)0)
{
//交换
Swap((char*)base+j*width,(char*)base+(j+1)*width,width);
}
}
}
}
void test4()
{
int arr[10]={9,8,7,6,5,4,3,2,1,0};
int sz = sizeof(arr) / sizeof(arr[0]);
//使用bubble_sort的程序员一定知道自己排序的是什么数据、
//就应该知道如何比较待排序数组中的元素
bubble_sort(arr,sz,sizeof(arr[0]),cmp_int);
int i = 0;
for (i=0;i<sz;i++)
{
printf("%d ",arr[i]);
}
}
void test5()
{
struct Stu s[3]={{"zhangsan",20},{"lisi",30},{"wangwu",10}};
int sz = sizeof(s) / sizeof(s[0]);
bubble_sort(s,sz,sizeof(s[0]),cmp_stu_by_age);
int k = 0;
for (k=0;k<sz;k++)
{
printf("%d " ,s[k].age);
//printf("%s " ,s[k].name);
}
}
int main()
{
//test1();
//test2();
//test3();
//test4();
test5();
return 0;
}
例题
```c
int main()
{
//数组名是首元素的地址
//1.sizeof(数组名) - 数组名表示首元素地址
//2.&数组名 - 数组名表示整个数组
//一维数组
int a[] = {1,2,3,4};//44=16
printf(“%d\n”,sizeof(a));//16-sizeof(数组名)-计算的是数组总大小-单位是字节
printf(“%d\n”,sizeof(a+0));//数组名这里表示首元素地址,a+0还是首元素地址,地址大小就是4/8个字节
printf(“%d\n”,sizeof(a));//4-数字名表示首元素地址,a就是首元素,sizeof(a)就是4
printf(“%d\n”,sizeof(a+1));//a+1第二个元素地址,地址大小为4/8
printf(“%d\n”,sizeof(a[1]));//4-第二个元素的大小
printf(“%d\n”,sizeof(&a));//&a取出的是数组的地址,数组的地址也是地址,地址大小为4/8
printf(“%d\n”,sizeof(*&a));//16 - &a是取数组的地址,数组的地址解引用访问的数组,sizeof计算的就是数组的大小单位是字节
printf(“%d\n”,sizeof(&a+1));//&a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址,所以是4/8
printf(“%d\n”,sizeof(&a[0]));//&a[0]是第一个元素的地址
printf(“%d\n”,sizeof(&a[0]+1));//&a[0]+1是第二个元素的地址
//字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n",sizeof(arr));//sizeof计算的是数组大小,6*1=6字节
printf("%d\n",sizeof(arr+0));//arr是首元素的地址,arr+0还是首元素的地址 地址的大小4/8
printf("%d\n",sizeof(*arr));//1 arr是首元素地址 *arr就是首元素 首元素是字符大小是一个字节
printf("%d\n",sizeof(arr[1]));//1
printf("%d\n",sizeof(&arr));//&arr 虽然是数组的地址,但还是地址,地址大小4/8
printf("%d\n",sizeof(&arr+1));//&arr+1 是跳过整个数组的地址,地址大小4/8
printf("%d\n",sizeof(&arr[0]+1));//第二个元素的地址,地址大小4/8
printf("%d\n",strlen(arr));//随机值1
printf("%d\n",strlen(arr+0));//随机值1
// printf("%d\n",strlen(*arr));//err
// printf("%d\n",strlen(arr[1]));//err
// printf("%d\n",strlen(&arr));//随机值1
// printf("%d\n",strlen(&arr+1));//随机值2 -6
// printf("%d\n",strlen(&arr[0]+1));//随机值3 -1
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 St0Bjahr!
评论
ValineDisqus