欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

指针总结(2)

程序员文章站 2024-01-01 20:05:16
...

指针:1、指针的总结;

2、理解指针数组;
3、理解数组指针;
4、理解函数指针;
5、理解函数指针数组(转移表);
6、理解指向函数指针数组的指针;
7、理解回调函数的使用;
8、练习使用qsort函数排序各种类型的数据;
9、模仿qsort的功能实现一个通用的冒泡排序;
10、几个指针和数组的相关练习。指针总结(2)
2、
指针总结(2)    
扩展:数组中存放的元素为指针类型:一级指针(int *arr[10])、二级指针(int **arr[10])...
指针的类型:整型指针(int *arr[10])、字符型指针(char *arr[10])、浮点型指针(float *arr[10])...
观察可知:指针数组的大小始终是:4*元素个数(指针就是地址,均占4字节)

3、

指针总结(2)
扩展:数组指针,指向数组的指针:该数组的类型可以是整型(int (*p)[10])、字符型(char (*p)[10])、浮点型(float (*p)[10])...
且数组的类型也可为指针类型,此时就是指针数组,则p为指向指针数组的数组指针(int *(*p)[10])
而将此指针存放在数组中,则p为指向指针数组的数组指针的指针数组(int *(*p[10])[10])
4、
指针总结(2)
扩展:函数指针,指向函数的指针,函数的返回值可以是整型(int (*pfun)( ))、字符型(char (*pfun)( ))、浮点型(float (*pfun)( ))...
函数的返回值也可以是指针类型(int * (*pfun)( ))、指针数组类型(int* (*pfun)[10]( ))、
数组指针类型(int (*)(*pfun)[10]( ))、
函数也可以是不同的参数列表,int (*pfun)(int, char)...

5、

指针总结(2)
扩展:函数指针数组是数组,是存放函数地址的数组,函数可以有参数(int (*parr[10])(int, char)),函数的返回值可以是整型、字符型、也可以是指针(int* (*parr[10])( ))...
应用:转移表的实现(简单计算器)
#include<stdio.h>
#include<assert.h>
#include<Windows.h>

#pragma warning(disable:4996)

//函数指针数组(转移表):简单计算器
int my_add(int a, int b)
{
	return  a + b;
}
int my_sub(int a, int b)
{
	return  a - b;
}
int my_mul(int a, int b)
{
	return  a * b;
}
int my_div(int a, int b)
{
	//assert(b != 0);
	if (!b){
		printf("error num2 by zero!\n");
		return -1;
	}
	return  a / b;
}

void menu()
{
	printf("******************************\n");
	printf("****  1:add        2:sub  ****\n");
	printf("****  3:mul        4:div  ****\n");
	printf("****        0:exit!       ****\n");
	printf("******************************\n");
	printf("please input your chioce!\n");
}

int main()
{
	//定义函数指针数组
	int(*parr[4])(int a, int b) = { my_add, my_sub, my_mul, my_div };
	int choice;
	int a, b;
	do{
		menu();
		scanf("%d", &choice);
		if (choice > 0 && choice <= 4){
			printf("please enter your nums<a, b>:");
			scanf("%d%d", &a, &b);
			printf("the result is: %d\n", parr[choice - 1](a, b));
		}
		else if (choice == 0){
			exit(0);
		}
		else{
			printf("input error! you should enter your choice at interval of [0,4]\n");
		}
	} while (1);

	system("pause");
	return 0;
}
6、
指针总结(2)
扩展:数组指针:int (*p)[10]; 当指针指向的这个数组是存放函数地址时,则p就是指向函数指针数组的指针(int *(*p)[10])( ))
注意:由于数组元素个数也是数组类型的一部分,所以此刻声明的指针变量中的[10]必须和它指向的函数指针数组的元素个数一致!!!
7、回调函数
    定义:将一个函数的指针(也就是该函数的地址)作为参数传递给另一个函数,当此函数指针被用来调用其所指向的函数时,此时,该函数指针指向的函数即为回调函数。
    作用:节省函数调用时间。
    应用:使用回调函数,模拟实现qsort(快排)。
8、练习使用qsort函数排序各种类型的数据:整型(int)、浮点型(double)、字符串(char *)。
认识qsort函数:Performs a quick sort.
    头文件:<stdlib.h>
    函数原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );  
有四个参数,第一个:要比较的数据(数组);
                    第二个:数据个数;
                    第三个:数据类型大小;
                    第四个:返回值为int型、参数列表为 const void *elem1, const void *elem2 的函数(该函数是自己实现的比较当前要排序的许多元素中的两个元素大小,并且返回1或-1或0(可根据升序降序自己设置)!!!(该函数就为回调函数)
#include<stdio.h>
#include<Windows.h>

int my_int_cmp(const void * num1, const void * num2)
{
	int *x = (int *)num1;
	int *y = (int *)num2;
	if (*x > *y){
		return 1;//升序
	}
	else if (*x < *y){
		return -1;
	}
	else{
		return 0;
	}
}

int my_double_cmp(const void * num1, const void * num2)
{
	double *x = (double *)num1;
	double *y = (double *)num2;
	if (*x > *y){
		return -1;//降序
	}
	else if (*x < *y){
		return 1;
	}
	else{
		return 0;
	}
}

int my_string_cmp(const void * num1, const void * num2)
{
	char **x = (char **)num1;//存放字符串地址的变量x
	char **y = (char **)num2;
	char *p1 = *x;//定义指针变量指向字符串
	char *p2 = *y;

	while (*p1 == *p2 && *p1 != '\0'){
		p1++; 
		p2++;
	}
	if (*p1 != *p2){//说明while循环跳出的原因是第一个条件不满足
		if (*p1 > *p2){
			return -1;//降序
		}
		else{
			return 1;
		}
	}
	else{//执行到这,说明while的第一个条件成立,第二个不成立,说明两个字符串相等
		return 0;
	}
}

int main()
{
	/*int arr1[] = { 1, 3, 2, 4, 1, 7, 6, 3, 8, 9 };
	int size = sizeof(arr1) / sizeof(arr1[0]);
	qsort(arr1, size, sizeof(int), my_int_cmp);*/

	/*double arr2[] = { 1.2, 4.3, 6.6, 2.1, 3.9, 5.8, 9.3, 0.3 };
	int size = sizeof(arr2) / sizeof(arr2[0]);
	qsort(arr2, size, sizeof(double), my_double_cmp);*/

	//字符串排序
	char *arr3[] = { "abcd", "abcde", "abce", "zxcbv", "zxca", "qwsa", "qeas" };
	int size = sizeof(arr3) / sizeof(arr3[0]);
	qsort(arr3, size, sizeof(char *), my_string_cmp);

	system("pause");
	return 0;
}

9、模仿qsort的功能实现一个通用的冒泡排序。

#include<stdio.h>
#include<Windows.h>

int my_int_cmp(const void * num1, const void * num2)
{
	int *x = (int *)num1;
	int *y = (int *)num2;
	if (*x > *y){
		return 1;//升序
	}
	else if (*x < *y){
		return -1;
	}
	else{
		return 0;
	}
}

int my_double_cmp(const void * num1, const void * num2)
{
	double *x = (double *)num1;
	double *y = (double *)num2;
	if (*x > *y){
		return -1;//降序
	}
	else if (*x < *y){
		return 1;
	}
	else{
		return 0;
	}
}

int my_string_cmp(const void * num1, const void * num2)
{
	char **x = (char **)num1;//存放字符串地址的变量x
	char **y = (char **)num2;
	char *p1 = *x;//定义指针变量指向字符串
	char *p2 = *y;

	while (*p1 == *p2 && *p1 != '\0'){
		p1++; 
		p2++;
	}
	if (*p1 != *p2){//说明while循环跳出的原因是第一个条件不满足
		if (*p1 > *p2){
			return -1;//降序
		}
		else{
			return 1;
		}
	}
	else{//执行到这,说明while的第一个条件成立,第二个不成立,说明两个字符串相等
		return 0;
	}
}

void my_swap(const void * num1, const void * num2, int size)
{
	//交换两个元素:按字节交换,交换size(类型大小)次
	char *p1 = (char *)num1;
	char *p2 = (char *)num2;
	int i = 0;
	while (i < size){
		char tmp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = tmp;
		i++;
	}
}

//模仿qsort的功能实现一个通用的冒泡排序
void my_qsort(void *base, int count, int size, int(*cmp)(const void *, const void *))
{
	for (int i = 0; i < count - 1; i++){
		int flag = 0;//冒泡优化
		for (int j = 0; j < count - 1 - i; j++){
			if (cmp((char *)base + size*j, (char *)base + size*(j + 1)) > 0){
				//base是void*,所以根据字节乘类型大小来确定比较元素的类型
				flag = 1;
				my_swap((char *)base + size*j, (char *)base + size*(j + 1), size);
			}
		}
	}
}

int main()
{

	/*int arr1[] = { 1, 3, 2, 4, 1, 7, 6, 3, 8, 9 };
	int size = sizeof(arr1) / sizeof(arr1[0]);
	my_qsort(arr1, size, sizeof(int), my_int_cmp);*/

	/*double arr2[] = { 1.2, 4.3, 6.6, 2.1, 3.9, 5.8, 9.3, 0.3 };
	int size = sizeof(arr2) / sizeof(arr2[0]);
	my_qsort(arr2, size, sizeof(double), my_double_cmp);*/

	//字符串排序
	char *arr3[] = { "abcd", "abcde", "abce", "zxcbv", "zxca", "qwsa", "qeas" };
	int size = sizeof(arr3) / sizeof(arr3[0]);
	my_qsort(arr3, size, sizeof(char *), my_string_cmp);

	system("pause");
	return 0;
}

指针总结(2)

指针总结(2)
指针总结(2)
10、练习指针与数组
#include<stdio.h>
#include<Windows.h>

void pointArr1()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int *p = (int *)(&a + 1);//下一个数组的地址,强转为int*则为跳过该数组的下一个地址(int *)
	printf("%d,%d", *(a + 1), *(p - 1));//2,5
}

void pointArr2()
{
	typedef struct
	{
		int num;//4
		char *pname;//4 
		short date;//2
		char ch[2];//1*2
		short year[4];//2*4
	}*p, test;//该结构体的大小:20
	p p1 = (p)malloc(sizeof(test));
	printf("%d\n", p1);//030A95A0
	printf("%d\n", p1 + 0x1);//030A95B4(p1+1实际是加上20)
	printf("%d\n", (unsigned long)p1 + 0x1);//030A95A1(此处p1是类型为无符号长整型变量+1就是+1)
	printf("%d\n", (unsigned int *)p1 + 0x1);//030A95A4(p1的类型为int*,加1就是加4)
}

void pointArr3()
{
	int a[4] = { 1, 2, 3, 4 };
	int *p1 = (int *)(&a + 1);//p1指向元素4后面的一个int大小的空间
	int *p2 = (int *)((int)a + 1);//p2指向从a首元素的第二个字节开始后面一个int大小的空间
	printf("%x,%x", p1[-1], *p2);//4(p1[-1] = *(p1-1)),2000000
}

void pointArr4()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	//注意:1、二维数组初始化时,一对{ }代表一个一维数组;
	//2、()代表一个元素,括号中是个逗号表达式,
	//所以数组int a[3][2] = {1, 3, 5}
	int *p;
	p = a[0];
	printf("%d", p[0]);//1(p[0] = *(p + 0))
}

void pointArr5()
{
	int a[5][5];
	int(*p)[4];//数组指针
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC(%p:表示无符号数),-4
}

void pointArr6()
{
	int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	//int a[2][5] = { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } };
	int *p1 = (int *)(&a + 1);//p1指向数组元素0后的一个int大小的地址空间
	int *p2 = (int *)(*(a + 1));//(a+1):代表数组a的第二个元素;
	//而*(a+1):代表当前指向数组的首元素;强转后,则p2就指向的元素是6的地址
	printf("%d,%d", *(p1 - 1), *(p2 - 1));//0,5
}

void pointArr7()
{
	char *a[] = { "work", "at", "abcd" };//指针数组
	char **pa = a;//指向数组
	pa++;//+1不是加1,实质上是加上每个字符串的大小
	printf("%s\n", *pa);//at
}

void pointArr8()
{
	char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
	char **cp[] = { c + 3, c + 2, c + 1, c };
	char ***cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *--*++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
}

int main()
{
	//pointArr1();
	//pointArr2();
	//pointArr3();
	//pointArr4();
	//pointArr5();
	//pointArr6();
	//pointArr7();
	pointArr8();

	system("pause");
	return 0;
}

pointArr3()详解指针总结(2)
pointArr5()详解指针总结(2)
pointArr8()详解指针总结(2)

上一篇:

下一篇: