关于指针的知识回顾

指针的知识回顾

//1.指针的输入特性。作为参数输入。
void printString(char *str)
{
	printf("%s\n",str+2); 
}
void printArray(int *arr,int len)
{
	for(int i=0;i<len;i++)
	{
		printf("%d  ",arr[i]);
		//printf("%d  ",*(arr+i));
	}
	printf("\n");
}
void printStringArray(char** arr,int len)
{
	//arr[0]==> *(arr+0)
	for(int i = 0;i<len;i++)
	{
		printf("%s\n",arr[i]);
	}
}
void test01()
{
	//在堆分配内存
	char *s = (char *)malloc(sizeof(char)*100); 
	//初始化
	memset(s,0,100);
	//赋值
	strcpy(s,"hello world!");
	printString(s); 
	//使用完释放内存 
	free(s);
	s = NULL;
	//在栈分配的内存 
	int arr[] = {1,2,3,4,5,6,7,8};
	int len = sizeof(arr)/sizeof(arr[0]);
	printArray(arr,len);
	char* strs[] = {(char *)"aaaaaa",(char*)"bbbbbb",(char*)"ccccccc",(char*)"ddddddd",(char*)"eeeeeeee"};
	int len2 = sizeof(strs)/sizeof(strs[0]);
	printStringArray(strs,len2);
}
//2.指针的输出特性
//①.用返回值输出 
int * getSpace(int len) 
{
	int *temp = (int *)malloc(sizeof(int)*len);
	for(int i = 0;i<len;i++)
	{
		temp[i] = 100+i;
	}
	return temp;
}
//②.作为函数参数
void getSpace2(int len,int **arr/*out*/) 
{
	int *temp = (int *)malloc(sizeof(int)*len);
	if(NULL==temp)
	{
		return;
	}
	for(int i = 0;i<len;i++)
	{
		temp[i] = 100+i;
	}
	*arr = temp;
}
void test02()
{
	int len = 10;
	int *p = getSpace(len);
	/*int *p = NULL;
	getSpace2(len,&p);*/   //作为参数的时候,由于栈区+局部变量的原因,需要使用二级指针。
	for(int i = 0;i<len;i++)
	{
		printf("%d \n",p[i]);
	}
}

真正在做开发的时候,需要进行充分的数据有效性验证,若为了无效的数据去申请占用资源是很浪费的。上面的代码可以这样写。

int getSpace3(int len,int **arr/*out*/) 
{
	if(len==0)
	{
		return -2;
	}
	int *temp = (int *)malloc(sizeof(int)*len);
	//temp = NULL;
	if(NULL==temp)
	{
		return -1;
	}
	for(int i = 0;i<len;i++)
	{
		temp[i] = 100+i;
	}
	*arr = temp;
	return 0;
} 
int main(int argc, char** argv) {
	int len = 10;
	int *p = NULL;
	int ret = 0;
	ret = getSpace3(len,&p);
	if(ret!=0)
	{
		printf("func getSpace3(int len,int **arr/*out*/) err : %d\n", ret);
		return -1;
	}
	for(int i = 0;i<len;i++)
	{
		printf("%d \n",p[i]);
	}
	return 0;
}

指针数组

关于指针步长,上一篇博客最后已经讨论过。
下面请看指针数组。所谓指针数组,就是数组的元素是指针,也就是数组的元素是地址。

int mysort(char** myArray, int len)
{
	if (NULL == myArray || len <= 0)
	{
		return -1;
	}
	for (int i = 0; i < len; i++)
	{
		for (int j = i + 1; j < len; j++)
		{
			if (strcmp(myArray[i], myArray[j]) > 0)
			{
				char* temp = myArray[i];
				myArray[i] = myArray[j];
				myArray[j] = temp;
			}
		}
	}
	return 0;
}
void printArray(char** myArray, int len)
{
	for (int i = 0; i < len; i++)
	{
		//printf("%s\n",myArray[i]);
		printf("%s\n", *(myArray + i));
	}
}
int main()
{
	//数组指针:指向某种数组 数据类型的指针 前面已经说过
	//指针数组:数组里的每一个元素都是指针 
	char* ptr[] = { (char *)"aaaaaa",(char*)"cccccccc",(char*)"eeeeee",(char*)"bbbbbb",(char*)"ddddddd" };
	cout << ptr[0] << endl;   //输出是aaaaaa
	cout << ptr << endl;     //输出是00EFF7B4
	cout << &ptr[0] << endl;   //输出是00EFF7B4
	//这个和普通的数组是一样的。
	int len = sizeof(ptr) / sizeof(char*);
	printf("len = %d\n", len);
	mysort(ptr, len);  //ptr代表的是第一个元素的地址,第一个元素又是地址。所以是 **
	printArray(ptr, len);
	return 0;
}
//堆区的指针数组
void test01()
{
	int len = 5;
	char **ptr = (char **)malloc(sizeof(char *)*len);
	for(int i = 0;i<len;i++)
	{
		ptr[i] = (char *)malloc(sizeof(char) *100);
		strcpy(ptr[i],"aaaaa");  //这里要注意的是这个for循环。
		//因为前面申请的是一个5个地址的数组,但是每个
		//地址并没有初始化,在此申请给它初始化。
	} 
	//使用
	for (int i = 0; i < len; i++)
	{
		free(ptr[i]);
		ptr[i] = NULL;
	}
	free(ptr);
	ptr = NULL;  //这是释放内存,一定要记得释放内存。
} 
//用完之后一定记得释放。
//具体使用场景
//找出关键字在表中的位置 
int findKeyPosition(char *table[]/*in*/,const char *key/*in*/,int *position/*out*/)
{  //这里的const char *key是希望不改变参数
	if(NULL == table || NULL == key || NULL == position)
	{
		return -1;
	}  //第一个异常  数据有效性验证
	for(int i = 0;table[i] != NULL; i++)
	{
		if(strcmp(key,table[i])==0)
		{
			*position = i;
			return 0;
		}
	}
	*position = -1;    //如果没找到,则位置置为-1
	return -2;
}
int main()
{
	char *pArray[] = {
		(char *)"for",   //vs2019默认的字符串常量是const的。每次都需要改一下。
		(char*)"do",
		(char*)"while",
		(char*)"case",
		(char*)"break",
		NULL
	};
	int position = 0;
	char* keyvalue = (char*)"break";
	int ret = 0;
	ret = findKeyPosition(pArray,keyvalue,&position);
	if(ret != 0)
	{
		printf("func findKeyPosition(char *table[]/*in*/,const char *key/*in*/,int *position/*out*/) err : %d\n",ret);
		return -1;
	}
	printf("position = %d\n",position);
	return 0;
}

函数指针

首先,这里需要把函数视为一个类型。

int func1(int a, int b)
{
	return a + b;
}
void test01()
{
	//定义函数类型 
	typedef int(my_func)(int, int);
	//定义函数指针 
	cout << func1 << endl;   //002E1604
	my_func* pFunc = func1;   //func1代表地址
	cout << pFunc << endl;   //002E1604
	int result = func1(10, 20);
	int resultp = pFunc(10, 20);
	cout << (*pFunc) << endl;   //这个也是002E1604   这个就很费解。
	//不过一样的地址才可以解释下面的这句话。
	int resultp2 = (*pFunc)(10, 20);
	printf("%d,%d,%d\n", result, resultp, resultp2);   //输出都是30.
	//接着直接定义函数指针类型 
	typedef int(*my_pfunc)(int, int);
	my_pfunc  pFunc2 = func1;
	printf("%d\n", pFunc2(10, 20));
	//接着直接定义函数指针变量
	int(*my_func_p)(int, int) = NULL;
	my_func_p = func1;
	printf("%d\n", my_func_p(10, 20));
}

函数指针做形参

int add3(int a, int b)
{
	return a + b - 10;
}
//函数指针作为另外一个函数的参数 
void test02(int(*pAdd)(int, int))   //表示一个函数指针变量 pAdd
{
	int a = 100;
	int b = 200;
	int result = pAdd(a, b);    //这个的pAdd在实际执行时,会得到add3的值,即地址。
	printf("result = %d\n", result);
}
//调用
test02(add3);

又来了,函数指针数组。

//函数指针数组
void test03()
{
	int (*pAdd[4])(int, int);
	pAdd[0] = add;
	pAdd[1] = add1;
	pAdd[2] = add2;
	pAdd[3] = add3;
    cout << pAdd << endl;   //输出是007EFAAC
	cout << &pAdd[0] << endl;  //输出是007EFAAC  说明这是一个普通数组。
	for (int i = 0; i < 4; i++)
	{
		int result = pAdd[i](10, 20);
		printf("%d\n", result);
	}
}

函数指针作为函数的参数,具体的一个应用场景,回调函数。
这是一个万能的打印数组的函数。void printAllArray(void* arr, int eleSize, int len, print_type print)
回调函数就是一个通过函数指针调用的函数。这里的printInt和printStruct就是回调函数。

void printInt(void* data)
{
	int* p = (int*)data;
	printf("%d  ", *p);
}
typedef struct Person
{
	char name[64];
	int age;
}person;
void printStruct(void* data)
{
	person* myPerson = (person*)data;
	printf("name:%s, age:%d\n", myPerson->name, myPerson->age);
}
typedef void(*print_type)(void*);   //定义一个函数指针的别名 print_type
/*
void *arr :待打印的数组
int eleSize: sizeof(数组元素的类型 )
int len:数组元素的个数
print_type print: 该函数实现不同类型数据的打印
*/
void printAllArray(void* arr, int eleSize, int len, print_type print)
{
	char* start = (char*)arr;
	for (int i = 0; i < len; i++)
	{
		char* endAddr = start + i * eleSize;
		print(endAddr);
	}
}
void test04()
{
	int arr[6] = { 11,22,33,44,55,66 };
	printAllArray(arr, sizeof(arr[0]), 6, printInt);
	//printInt代表的是地址。前面定义的函数形参是指针,符合。
	printf("\n");
	//结构体数组
	person persons[] = {
		{"aaaa",20},
		{"bbbb",30},
		{"cccc",40},
	};
	printAllArray(persons, sizeof(person), 3, printStruct);
}

指针函数

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#pragma warning(disable:4996)   //VS2019加上这句话,不然他会认为strcpy函数不安全
//指针函数: 它是一个函数,返回值是指针
typedef struct Person{
	char name[64];
	int age;
}Person; 

Person * getAperson(char *name,int age)
{
	Person * newPerson = (Person *)malloc(sizeof(Person));
	strcpy(newPerson->name,name);
	newPerson->age = age;
	return newPerson;
}

int main(int argc, char** argv) {
	Person *p = getAperson((char*)"小白",20);
	printf("p->name:%s , p->age:%d\n",p->name,p->age);
	return 0;
}

好了,关于指针的知识回顾就是这么多。谢谢阅读。

发布了27 篇原创文章 · 获赞 0 · 访问量 426

猜你喜欢

转载自blog.csdn.net/weixin_40007143/article/details/103748343