指针的知识回顾
//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;
}
好了,关于指针的知识回顾就是这么多。谢谢阅读。