C语言总结5--指针下

  • 字符指针

  char *(变量名)

#include<stdio.h>
int main()
{char ch='w';
char *p=&ch;
printf("%c\n",*p);//指针类型为char型 解引用只能有1字节
return 0;
}
#include<stdio.h>
int main()
{char *p="hello world";//指针p中放的是字符串的首地址 
printf("%s\n",p);//字符串在字符常量区 不能通过指针P来修改 
return 0;//指针P在栈上了开辟4字节
}
#include<stdio.h>
int main()
{
char str1[]="hello bit";//str1和str2分别指向两个地址 地址不同
char str2[]="hello bit";
char *str3="hello bit";//str3和str4指向同一个字符串
char *str4="hello bit";//只开辟了一份 str3和str4指向同一字符串(地址相同)
if(str1==str2)
{printf("str1 and str2 are same\n");
}
else {printf("str1 and str2 are different\n");
}
if(str3==str4)
{printf("str3 and str4 are same\n");
}
else{printf("str3 and str4 are different\n");
}
return 0;
}

       

  • 数组指针

数组指针是指针,是能够指向数组的指针
int (*p)[10]  整型数组指针(看优先级 先和*结合 在和数组结合)

#include<stdio.h>
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,0};
int (*p)[10]=&a;//&a为数组的地址 
return 0;
}
  •  数组参数和指针参数

1. 数组传参要降维降维成指向其内部元素类型的指针
 一维数组传参下标可省略
 二维以上数组传参时只有第一个下标可省略 其余都不可以
数组的下标也是数组类型的一部分 

#include <stdio.h>

void Print_a1(int(*a)[5],int row, int col)//数组指针
{ 
	int i = 0;//数组传参要降维 降维成指向其内部元素类型的指针
for (; i<row; i++)
{
	int j = 0;
	for (; j<col; j++)
	{
		printf("%d\n", a[i][j]);
	}
}
printf("\n");
}

void Print_a(int a[3][5],int row, int col)
{ 
	int i = 0;
for (; i < row; i++)
{
	int j = 0;
	for (; j < col; j++)
	{
		printf("%d\n", a[i][j]);
	}
}
printf("\n");
}


int main()
{
	int a[3][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//二维数组的首元素是一维数组的第一行
	int r = 3;
	int c = 5;
	Print_a(a,r, c);//传递的a其实相当于第一行的地址,是一维数组的地址
	Print_a1(a,r, c);
	system("pause");
	return 0;
}


   2.一维数组传参

void test(int a[])//也可写成int a[10]或int *a(数组传参要降维 降维成指向其内部元素类型的指针) 内部元素类型为int 
{}
void test1(int **a1)//数组传参要降维 内部元素为一级指针 也可写成 int *a1[20]
{}
int main()
{int a[10]={0};
int *a1[20]={0};//指针数组
test(a);
test1(a1);
}

 3.二维数组传参
 二维数组传参,函数形参的设计只能省略第一个[ ]的数字(对于一个二维数组,可以不知道有多少行,但必须知道一行有多少元素)
 

二维数组传参的三种方式:

#include<stdio.h>
void test(int a[3][5])
{}
void test(int a[][5])
{}
void test(int (*a)[5])//数组传参要降维 降维成指向其内部元素类型的指针 内部元素类型为一维数组 则降维成一维整型数组指针
{}
int main()
{int a[3][5]={0};
test(a);
return 0;
}

  4.一级指针传参

#include<stdio.h>
void print(int *p,int sz)//也可写成int p[] 伪装成数组的指针 
{int i=0;
for(;i<sz;i++)
{printf("%d\n",*(p+i));}//p[i]
}
int main()
{int a[10]={1,2,3,4,5,6,7,8,9,0};
int *p=a;
int sz=sizeof(a)/sizeof(a[0]);
print(p,sz);
return 0;
}

 5.二级指针传参

#include<stdio.h>
void test(int **pi)
{printf("num=%d\n",**pi);//**pi=n=10
}
int main()
{ int n=10;
int *p=&n;
int **pp=&p;
int *a[10];//指针数组
test(pp);
test(&p);
test(a);
return 0;
}
  •  函数指针

函数指针是保存函数的地址
函数名或取地址函数名都表示取地址

eg: void (*pfun1)()  函数指针

void(*pfun_t)(int) 函数指针

扫描二维码关注公众号,回复: 13147845 查看本文章

函数调用的本质:程序调转到目标函数入口地址处
 

#include<stdio.h>
void print()
{printf("haha\n");
}
int main()
{
printf("%p\n",print);
printf("%p\n",&print);
return 0;
}

(*(void(*)())0)();函数指针

void (*signal(int,void(*)(int)))(int);返回值为函数指针的函数声明

  •  函数指针数组和转移表

把函数的地址存到一个数组中,那么这个数组就叫函数指针数组
int (*p[10])( )    函数指针数组
函数指针数组的用途:转移表

例题:计算器

#include<stdio.h>
#include<Windows.h>
#pragma warning (disable:4996)
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;
}
int main()
{
    int x, y;
    int input = 1;
    int ret = 0;
    int(*p[5])(int x, int y) = { 0, add, sub, mul, Div };//转移表
    while (input)
    {
        printf("******************************\n");
        printf("          1.add 2.sub         \n");
        printf("          3.mul 4.div         \n");
        printf("******************************\n");
        printf("请选择:\n");
        scanf("%d", &input);
        if ((input <= 4 && input >= 1))
        {
            printf("输入操作数:\n");
            scanf("%d %d", &x, &y);
            ret = ((*p[input])(x, y));
        }
        else{
            printf("输入有误\n");
            continue;
        }
        printf("ret=%d\n", ret);
    }
    system("pause");
    return 0;
}
  • 指向函数指针数组的指针

指向函数指针数组的指针是一个指针,指针指向一个数组,数组元素都是函数指针

#include<stdio.h>
void test(const char *str)
{printf("%s\n",str);
}
int main()
{void (*pfun)(const char *)=test;//返回值为void 参数为const char * 的函数指针 函数指针保存函数地址
void (*pfun1[5])(const char *str);//函数指针数组 数组里放函数的地址
pfun1[0]=test;
void (*(*pfun2)[10])(const char *)=&pfun1;//指向函数指针数组pfun1的指针pfun2
return 0;
}
  • 回调函数

回调函数就是一个通过函数指针调用的函数
如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数

1.qsort 函数可以任意类型进行排序,但需要使用者实现一个比较函数
声明:
void qsort(void *base,size_t nitems,size_t size,int (*compar)(const void *,const void *))
base: 指向要排序的数组的第一个元素的指针
nitems:由base指向的数组中的元素个数
size:数组中每个元素的大小,以字节为单位
compar:用来比较两个元素的函数

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
int int_cmp(const void *p1, const void *p2)//回调函数
{
    int *x = (int *)p1;
    int *y = (int *)p2;
    if (*x > *y)
    {
        return 1;
    }
    else if(*x==*y)
    {
        return 0;
    }
    else{
        return -1;
    }
}
int main()
{
    int a[] = { 12, 3, 56, 2, 62, 4, 1, 7, 9, 21 };
    qsort(a, sizeof(a) / sizeof(a[0]), sizeof(int), int_cmp);
    int i = 0;
    for (; i<sizeof(a) / sizeof(a[0]); i++)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    system("pause");
    return 0;
}

 2. 模拟实现qsort(采用冒泡的方式)

#include<stdio.h>
#include<Windows.h>
int int_cmp(const void* p1, const void* p2)
{
	int *x = (int*)p1;//强转类型
	int *y = (int*)p2;
	if (*x > *y)
	{
		return 1;
	}
	else if (*x == *y)
	{
		return 0;
	}
	else
	{
		return -1;
	}
	//或者
	//return (*(int *)p1 - *(int *)p2);
}
void Swap(char* p1, char* p2,int size)
{
	while (size--)//一个字节一个字节的交换
	{
		*p1 ^= *p2;
		*p2 ^= *p1;
		*p1 ^= *p2;
		p1++;
		p2++;
	}
}
void my_qsort(void* base, size_t num, size_t size, int(*compare)(const void*,const void*))
{
	char* p = (char*)base;//通过char一次操纵一个字节
	//冒泡思想:从前往后,相邻两个元素之间进行比较,将大的元素依次向后排;第二次进行比较时,重复之前步骤,不对第一个元素进行重复;数组长度为n,重复上述步骤n-1次
	for (unsigned int i = 0; i < num-1; i++)//冒泡的轮次
	{
		int flag = 0;
		for (unsigned int j = 0; j < num-1-i; j++)//减i是说明此数已经交换过了,不需要再进行交换
		{
			if (compare(p+j*size,p+(j+1)*size)>0)
			{
				Swap(p+j*size,p+(j+1)*size,size);
				flag = 1;
			}
		}
		if (!flag)//控制交换完成
		{
			break;
		}
	}
}
int main()
{
	int arr[] = { 7, 1, 2, 4, 5, 3, 9, 0, 6 };
	int i = 0;
	//void qsort(void* base,size_t num,size_t size,int(*compare)(cosnt void*,const void*))
	my_qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43807876/article/details/114823319