C/C++语言是一种通用的编程语言,具有高效、灵活和可移植等特点。C语言主要用于系统编程,如操作系统、编译器、数据库等;C语言是C语言的扩展,增加了面向对象编程的特性,适用于大型软件系统、图形用户界面、嵌入式系统等。C/C++语言具有很高的效率和控制能力,但也需要开发人员自行管理内存等底层资源,对于初学者来说可能会有一定的难度。
定义并使用一维数组: 该数组是最通用的数组,也是最基本的.
#include <stdio.h> void PrintArray (int *Array, int len) { for (int x = 0 ; x < 10 ; x++) { printf ("%d \n" , Array[x]); } } int main (int argc, char * argv[]) { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; PrintArray(Array, 10 ); system("pause" ); return 0 ; }
定义并使用二维数组: 二维数组是相对于一维数组而言的,在内存中其都是一段线性的连续的存储空间.
#include <stdio.h> int main (int argc, char *argv[]) { int array [2 ][3 ] = { { 1 , 2 , 3 }, { 4 , 5 , 6 } }; int *Pointer1 = &array [0 ][0 ]; printf ("array[0][0]基址:%x \n" , Pointer1); printf ("array[0][0]数据:%d\n" , *(Pointer1)); printf ("arrya[0][1]数据:%d\n" , *(Pointer1 + 1 )); int *Pointer2 = &array [1 ][2 ]; printf ("array[1][2]基址: %x \n" , Pointer2); printf ("数组元素个数:%d\n" , sizeof (array ) / sizeof (int )); return 0 ; }
使用指针遍历数组: 使用指针定位数组,并输出数组元素.
#include <stdio.h> int main (int argc, char * argv[]) { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int *ptr; for (ptr = &Array; ptr < (Array + 10 ); ptr++) { printf ("%d " , *ptr); } system("pause" ); return 0 ; }
动态数组的定义: 我们可以自己手动分配空间并定义一个动态数组.
#include <stdio.h> #include <stdlib.h> int main (int argc, char * argv[]) { int ** p = (int **)malloc (sizeof (int *)* 3 ); p[0 ] = (int *)malloc (sizeof (int )* 3 ); p[1 ] = (int *)malloc (sizeof (int )* 3 ); p[2 ] = (int *)malloc (sizeof (int )* 3 ); p[0 ][0 ] = 1 ; p[0 ][1 ] = 2 ; p[0 ][2 ] = 3 ; p[1 ][0 ] = 4 ; for (int x = 0 ; x < 3 ; x++) printf ("%d \n" , p[0 ][x]); system("pause" ); return 0 ; }
指针与数组之间的运算: 通过将两个指针做减法,我们就可以得到两个元素之间相差多少字节.
#include <stdio.h> #include <stdlib.h> #include <string.h> int main (int argc, char * argv[]) { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int *ptr = Array; ptr = &Array[10 ]; int ptr_len = ptr - &Array[0 ]; int arr_len = ptr - Array; printf ("当前Array数组总长度: %d %d\n" , ptr_len, arr_len); int *ptr1 = &Array[0 ]; int *ptr2 = &Array[7 ]; int ptr3_len = ptr2 - ptr1; printf ("Array[7] - Array[0] 相隔 %d 个元素 %d 个字节 \n" , ptr3_len,ptr3_len * 4 ); system("pause" ); return 0 ; }
定义一维指针数组: 所为指针数组就是说该数组是用来存放其他的变量地址的,故称为指针数组.
#include <stdio.h> #include <stdlib.h> #include <string.h> void PrintInt () { int x = 10 , y = 20 , z = 30 ; int *Array[] = { &x, &y, &z }; *Array[0 ] = 100 ; *Array[2 ] = 300 ; for (int x = 0 ; x < 3 ; x++) printf ("地址: %x --> 数值:%d \n" , Array[x], *(Array[x])); } void PrintArray () { int x[] = { 1 , 2 , 3 , 4 , 5 }; int y[] = { 6 , 7 , 8 , 9 , 10 }; int *Array[] = { &x, &y }; printf ("单独取地址: %x --> 取值: %d \n" , (Array[0 ]+1 ),*(Array[0 ] + 1 )); for (int x = 0 ; x < 2 ; x++) { for (int y = 0 ; y < 5 ; y++) { printf ("循环取地址: %x --> 数值: %d \n" , Array[x] + y, *(Array[x] + y)); } } } int main (int argc, char * argv[]) { PrintArray(); system("pause" ); return 0 ; }
定义二维指针数组: 同理我们可以通过指针遍历到二维数组中的数据,三维四维以此类推.
#include <stdio.h> #include <stdlib.h> void PrintArray (int (*Array)[3 ], int row, int col) { for (int x = 0 ; x < row; ++x) { for (int y = 0 ; y < col; ++y) { printf ("地址: %x --> 遍历数组: %d \n" , (*(Array + x) + y), Array[x][y]); } } } int main (int argc, char * argv[]) { int Array[2 ][3 ] = { { 1 , 2 , 3 }, { 4 , 5 , 6 } }; int (*pArray) = Array; printf ("寻找 Array[0][0] --> %d \n" , (*pArray + 0 )); printf ("寻找 Array[0][1] --> %d \n" , (*pArray + 1 )); printf ("寻找 Array[1][2] --> %d \n" , (*pArray + 1 ) + 2 ); printf ("寻找 Array[1][3] --> %d \n" , (*pArray + 1 ) + 3 ); PrintArray(Array, 2 , 3 ); system("pause" ); return 0 ; }
数组实现逆序排列: 所谓数组逆序就是讲一个正向数组反向排列,并输出排序后的结果.
#include <stdio.h> void Swap_Array (int Array[], int Number) { int x = 0 ; int y = Number - 1 ; while (x < y) { int tmp; tmp = Array[x]; Array[x] = Array[y]; Array[y] = tmp; x++; y--; } } int main (int argc, char * argv[]) { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; Swap_Array(Array, 10 ); for (int x = 0 ; x < 10 ; x++) { printf ("%d " , Array[x]); } system("pause" ); return 0 ; }
用数组冒泡排序: 冒泡排序是经典的算法,也是学习数组必学知识点,这里总结一份冒泡排序.
#include <stdio.h> #include <stdlib.h> #include <string.h> void bubble (int *arr, int len) { int flag = 1 ; for (int i = 0 ; i < len - 1 ; i++) { for (int j = 0 ; j < len - i - 1 ; j++) { if (arr[j] > arr[j + 1 ]) { flag = 0 ; int temp = arr[j]; arr[j] = arr[j + 1 ]; arr[j + 1 ] = temp; } } if (flag) return ; flag = 1 ; } } int main (int argc, char * argv[]) { int Array[] = {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; int len = sizeof (Array) / sizeof (int ); bubble(Array, len); for (int x = 0 ; x < len; x++) printf ("%d \n" , Array[x]); system("pause" ); return 0 ; }
定义常量指针: 一般为了高效传递数据,我们使用地址传递,这样就无须重复拷贝了,通常会加上常指针防止数据被误修改.
#include <stdio.h> #include <stdlib.h> struct Student { int num; char *name; }; void MyPrint (const struct Student *stu) { struct Student *p = (struct Student *)stu; p->num = 100 ; printf ("内部的打印: %d \n" , stu->num); } int main (int argc, char * argv[]) { struct Student stu = { 1 , "lyshark" }; MyPrint(&stu); printf ("外部的打印: %d \n" , stu.num); system("pause" ); return 0 ; }
多级指针与野指针: 多级指针就是指针变量中存储有另一个指针变量,野指针就是非法指针,该指针被指向一段非法内存.
#include <stdio.h> #include <string.h> void MyPrintA () { int number = 10 ; int *ptr1 = &number; int **ptr2 = &ptr1; printf ("二级: %x --> 一级: %x --> 数据: %x (%d) \n" ,ptr2,ptr1,&number,number); int age = 20 ; int *ptr3 = &age; int **ptr4 = &ptr3; int ***ptr5 = &ptr4; ***ptr5 = 100 ; printf ("三级: %x --> 二级: %x --> 一级: %x --> 数据: %x (%d) \n" , ptr5,ptr4,ptr3,&age,age); } void MyPrintB () { int number = 10 ; int *ptr = &number; ptr = 0xffff ; *ptr = 200 ; } int main (int argc, char * argv[]) { MyPrintA(); system("pause" ); return 0 ; }
指针的步长与取值: 指针与指针之间可以强制类型转换通过步长索引元素,offsetof()
可用于计算步长.
#include <stdio.h> #include <stddef.h> void MyPrintA () { char buf[1024 ] = { 0 }; int number = 10 ; int name = 20 ; memcpy (buf + 1 , &number, sizeof (int )); memcpy (buf + 5 , &name, sizeof (int )); char *number_ptr = buf; int number_tmp = *(int *)(number_ptr + 1 ); printf ("取出buf里面的4字节(int) --> 地址: %x --> 数据: %d \n" , &number_tmp, number_tmp); char *name_ptr = buf; int name_tmp = *(int *)(name_ptr + 5 ); printf ("取出buf里面的4字节(int) --> 地址: %x --> 数据: %d \n" , &name_tmp, name_tmp); } void MyPrintB () { struct Person { int num; char name[64 ]; int age; }; struct Person stu = { 1 , "lyshark" , 23 }; printf ("age相对于Person首地址偏移量: %d \n" , offsetof(struct Person, age)); int struct_age = *(int *)((char *)&stu + offsetof(struct Person, age)); printf ("结构体Person中的 Age 的数据 --> %d \n" , struct_age); int struct_name = ((char *)&stu + offsetof(struct Person, name)); printf ("结构体Person中的 Name 的数据 --> %s \n" , struct_name); } int main (int argc, char * argv[]) { MyPrintB(); system("pause" ); return 0 ; }
指针的间接赋值: 指针变量与普通变量赋值不同,指针代表一个地址,当该地址中的值被改变时,指向的变量都会发生变化.
#include <stdio.h> #include <stdlib.h> #include <string.h> void ChangeValue (int *ptr) { (*ptr) = 200 ; } void ChangePointer (int **val) { *val = 0x09 ; } int main (int argc, char * argv[]) { int number = 100 ; ChangeValue(&number); printf ("改写后的数值: %d --> 当前number地址: %x \n" , number, &number); int *ptr = NULL ; ChangePointer(&ptr); printf ("改写后的数值: %d --> 当前ptr地址: %x \n" , ptr,&ptr); system("pause" ); return 0 ; }
定义Void万能指针: 万能指针就是什么数据类型的数据都能指,但是在指向其他数据时必须经过转换才可使用.
#include <stdio.h> #include <stdlib.h> #include <string.h> void MyPrintA () { int number = 10 ; void *int_ptr = &number; *(int *)int_ptr = 100 ; printf ("数值: %d --> 地址: %x \n" , number, int_ptr); } void MyPrintB () { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; void *array_ptr = Array; *(int *)array_ptr = 100 ; *((int *)array_ptr + 1 ) = 200 ; for (int x = 0 ; x < 10 ; x++) printf ("输出指针: %x 数据: %d \n" , ((int *)array_ptr+x),Array[x]); } void MyPrintC () { int Array[2 ][3 ] = { { 1 , 2 , 3 }, { 4 , 5 , 6 } }; void *array_ptr = Array; printf ("Array[0][0] -> %d \n" , *((int *)array_ptr + 0 )); printf ("Array[1][0] -> %d \n" , *(((int *)array_ptr + 0 ) + 3 )); printf ("Array[1][1] -> %d \n" , *(((int *)array_ptr + 1 ) + 3 )); } int main (int argc, char * argv[]) { MyPrintC(); system("pause" ); return 0 ; }
Calloc 分配堆指针: calloc()
函数,主要用于一次性分配内存空间,与之相似的函数有malloc()
使用与其大同小异.
#include <stdio.h> #include <stdlib.h> int main (int argc, char * argv[]) { int *ptr = calloc (10 , sizeof (int )); for (int x = 0 ; x < 10 ; x++) ptr[x] = x + 1 ; for (int x = 0 ; x < 10 ; x++) printf ("堆地址: %x --> 数据: %d \n" , &ptr[x], ptr[x]); if (ptr != NULL ) { free (ptr); ptr = NULL ; } system("pause" ); return 0 ; }
Realloc 扩充堆指针: 当堆空间容量不足时,我们就可以使用Realloc()
函数对堆空间进行动态的扩容.
#include <stdio.h> #include <stdlib.h> int main (int argc, char * argv[]) { int *ptr = malloc (sizeof (int )* 10 ); for (int x = 0 ; x < 10 ; x++) { ptr[x] = x; printf ("堆地址: %x --> 数据: %d \n" , &ptr[x],ptr[x]); } int old_ptr = ptr; ptr = realloc (ptr, sizeof (int ) * 200 ); int new_ptr = ptr; if (old_ptr != new_ptr) printf ("原始空间: 0x%x --> 新空间: 0x%x \n" , old_ptr, new_ptr); else printf ("原始空间: 0x%x 没有发生变化.\n" ,old_ptr); system("pause" ); return 0 ; }
定义指向数组的指针: 通过typedef()
方式重定义指向数组的指针变量,并可以通过指针灵活的遍历输出.
#include <stdio.h> #include <stdlib.h> void MyPrintA () { typedef int (Array_Type) [10]; Array_Type MyArray; for (int x = 0 ; x < 10 ; x++) { MyArray[x] = x; printf ("输出 MyArray --> %d \n" , MyArray[x]); } Array_Type *pArray = &MyArray; for (int x = 0 ; x < 10 ; x++) { int Number = *(*pArray + x); printf ("遍历 MyArray --> %d \n" , Number); } } void MyPrintB () { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; typedef int (*Array_Point) [10]; Array_Point pArray_Point = &Array; for (int x = 0 ; x < 10 ; x++) printf ("遍历 pArray_Point --> %d \n" , *(*pArray_Point + x)); } void PrintC () { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int (*pArray_Param)[10 ] = &Array; for (int x = 0 ; x < 10 ; x++) printf ("遍历 pArray_Param --> %d \n" , *(*pArray_Param + x)); } int main (int argc, char * argv[]) { PrintC(); system("pause" ); return 0 ; }
用指针实现冒泡排序: 通过指针的方式实现冒泡排序算法,主要是练习一下指针的使用技巧.
#include <stdio.h> #include <stdlib.h> #include <string.h> void BubbleSort (int *Array, int len) { for (int x = 0 ; x < len - 1 ; x++) { for (int y = 0 ; y < len - 1 - x; y++) { if (*(Array + y) > *(Array + y + 1 )) { int tmp = *(Array + y); *(Array+y) = *(Array + y + 1 ); *(Array + y + 1 ) = tmp; } } } } int main (int argc, char * argv[]) { int Array[10 ] = { 4 ,7 ,8 ,2 ,1 ,8 ,9 ,3 ,4 ,10 }; int len = sizeof (Array) / sizeof (Array[0 ]); int *ptr = Array; BubbleSort(ptr, len); for (int x = 0 ; x < 10 ; x++) { printf ("%d " , *(ptr+x)); } system("pause" ); return 0 ; }
用指针实现选择排序: 针对字符串的选择排序,从小到大排列,这里我们使用了二级指针作为函数参数.
#include <stdio.h> #include <stdlib.h> #include <string.h> void PrintArray (char **Array,int len) { for (int x = 0 ; x < len; ++x) printf ("%s \n" , Array[x]); } void SelectSort (char **Array, int len) { for (int x = 0 ; x < len; ++x) { int min = x; for (int y = x + 1 ; y < len; ++y) { if (strcmp (Array[y], Array[min]) < 0 ) min = y; } if (min != x) { char *tmp = Array[min]; Array[min] = Array[x]; Array[x] = tmp; } } } int main (int argc, char * argv[]) { char *pArray[] = { "ddd" , "bbb" ,"sss" , "qqq" , "yyy" , "eee" , "ooo" }; int len = sizeof (pArray) / sizeof (char *); SelectSort(pArray, len); PrintArray(pArray, len); system("pause" ); return 0 ; }
用指针完成数组逆序: 用指针实现逆序存放数组元素值,所谓逆序就是将传入的数组顺序反向颠倒.
#include <stdio.h> int ArrayReverse (int *Array, int len) { int *Ptr, *StartPtr, *EndPtr, Middle, Temporary; StartPtr = Array; EndPtr = Array + len - 1 ; Middle = (len - 1 ) / 2 ; Ptr = Array + Middle; for (StartPtr = Array; StartPtr <= Ptr; StartPtr++, EndPtr--) { Temporary = *StartPtr; *StartPtr = *EndPtr; *EndPtr = Temporary; } return 0 ; } int main (int argc, char * argv[]) { int Array[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 }; ArrayReverse(&Array, 10 ); for (int x = 0 ; x < 10 ; x++) printf ("%d " , Array[x]); system("pause" ); return 0 ; }
用指针查找最大最小值: 使用指针查找数列中最大值/最小值,找到后分别返回到两个变量中.
#include <stdio.h> int Lookup_Max_Min (int *Array, int len,int *max,int *min) { int *ptr; *max = *min = *Array; for (ptr = Array + 1 ; ptr < Array + len; ptr++) { if (*ptr > *max) *max = *ptr; else if (*ptr < *min) *min = *ptr; } return 0 ; } int main (int argc, char * argv[]) { int Array[10 ] = { 6 ,5 ,7 ,8 ,9 ,0 ,3 ,2 ,1 ,5 }; int Array_Max, Array_Min; Lookup_Max_Min(&Array, 10 ,&Array_Max,&Array_Min); printf ("最大值: %d --> 最小值: %d \n" , Array_Max, Array_Min); system("pause" ); return 0 ; }
指针实现数组操作: 如下案例中演示了利用指针实现基本取值,基本替换,正反向遍历等操作.
#include <stdio.h> #include <Windows.h> int main (int argc, char * argv[]) { int Array[] = {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; DWORD *PEB = (DWORD *)Array; DWORD *Ldr = *((DWORD **)((DWORD *)Array + 1 )); printf ("Ldr = > %x Value = %d \n" , &Ldr,Ldr); printf ("PEB = %x &PEB = %x \n" , PEB, &PEB); Ldr = (DWORD *)&PEB; printf ("LDR = %x &LDR = %x *LDR = %x \n" , Ldr, &Ldr, *Ldr); printf ("(unsigned char *)PEB = %x \n" , (unsigned char *)PEB); printf ("(unsigned char *)PEB + 4 = %x \n" , (unsigned char *)PEB + 4 ); printf ("取出第一个元素内存地址: %x \n" , (DWORD **)((unsigned char *)PEB + 4 )); printf ("取出其中的值: %d \n" , *(DWORD **)((unsigned char *)PEB + 4 )); DWORD ref = (DWORD)*((unsigned char *)Array + 4 ); *((DWORD *)(Array + 1 )) = 10 ; printf ("取出的值: %d 替换后: %d \n" , ref, *((DWORD *)(Array + 1 ))); for (int x = 0 ; x < 10 ; x++) { DWORD ref1 = *((DWORD *)((unsigned char *)Array + (x * 4 ))); printf ("正向元素输出: %d \n" , ref1); } DWORD *Frist = NULL ; DWORD *Last = NULL ; for (int x = 0 ; x < 10 ; x++) { Frist = *(DWORD **)((DWORD *)Array + x); Last = (DWORD *)((DWORD *)Array + (9 - x)); printf ("反向输出: %d --> %d \n" , Frist, *Last); } system("pause" ); return 0 ; }
指针定位多维数组: 以下案例通过指针定位二三维指针数组中的元素,并输出元素值.
#include <stdio.h> #include <Windows.h> int main (int argc, char * argv[]) { DWORD Array[] = { 1 , 2 , 3 , 4 , 5 }; DWORD *ArrayPtr[] = { &Array[0 ], &Array[1 ], &Array[2 ], &Array[3 ], &Array[4 ] }; DWORD *ArrayPtrS[] = { ArrayPtr[0 ], ArrayPtr[1 ], ArrayPtr[2 ], ArrayPtr[3 ], ArrayPtr[4 ] }; DWORD *PEB; PEB = *((DWORD **)((DWORD *)ArrayPtr + 1 )); printf ("%x %d \n" , PEB,*PEB); PEB = *((DWORD **)((DWORD *)(ArrayPtr + 1 ))); printf ("%x %d \n" , PEB, *PEB); PEB = *(DWORD **)((unsigned char *)(ArrayPtr) + (1 *4 )); printf ("%x %d \n" , PEB, *PEB); PEB = *(DWORD **)ArrayPtr; printf ("得到ArrayPtr地址: %x --> 得到Array元素地址: %x --> 得到元素值: %x \n" , &PEB,PEB,*PEB); printf ("得到第一个指针地址: %x \n" , (DWORD)*(DWORD **)ArrayPtr); printf ("得到第二个指针地址: %x --> 数据: %d \n" , (*((DWORD **)ArrayPtr) + 1 ), *(*((DWORD **)ArrayPtr) + 1 )); printf ("原始数据为: %x \n" , *ArrayPtr[1 ]); *((DWORD *)(ArrayPtr + 1 )) = (DWORD)*(DWORD **)ArrayPtr; printf ("更改数据为: %x \n" , *ArrayPtr[1 ]); printf ("原始指针数据为: %x \n" , *ArrayPtr[1 ]); **((DWORD **)(ArrayPtr + 1 )) = (DWORD)*(DWORD **)ArrayPtr; printf ("更改指针数据为: %x \n" , *ArrayPtr[1 ]); for (int x = 0 ; x < 5 ; x++) { printf ("地址: %x --> 数据: %d \n" , (*((DWORD **)ArrayPtr) + x), *(*((DWORD **)ArrayPtr) + x)); } system("pause" ); return 0 ; }
同理三维指针的定位同样如此,只是在解析时需要多加一层即可取出数据.
#include <stdio.h> #include <Windows.h> int main (int argc, char * argv[]) { DWORD Array[] = { 1 , 2 , 3 , 4 , 5 }; DWORD *ArrayPtr[] = { &Array[0 ], &Array[1 ], &Array[2 ], &Array[3 ], &Array[4 ] }; DWORD *ArrayPtrS[] = { ArrayPtr[0 ], ArrayPtr[1 ], ArrayPtr[2 ], ArrayPtr[3 ], ArrayPtr[4 ] }; DWORD *PtrA = (DWORD *)((DWORD **)((DWORD ***)ArrayPtrS)); printf ("获取到ArrayPtr[0]地址 = %x \t 获取到Array[0]地址 = %x \n" , PtrA,*PtrA); DWORD *PtrB = (DWORD *)((DWORD **)((DWORD ***)(ArrayPtrS + 1 ))); printf ("获取到ArrayPtr[1]地址 = %x \t 获取到Array[1]地址 = %x \n" , PtrB, *PtrB); DWORD PtrC = *((DWORD *)((DWORD **)((DWORD ***)(ArrayPtrS + 1 )))); printf ("获取到里面的数值: %d \n" , *(DWORD *)PtrC); printf ("ArrayPtrS => " ); for (int x = 0 ; x < 5 ; x++) printf ("0x%x " , &ArrayPtrS[x]); printf ("\n" ); printf ("ArrayPtr => " ); for (int x = 0 ; x < 5 ; x++) printf ("0x%x " , ArrayPtr[x]); printf ("\n" ); DWORD *PtrBB = ((DWORD *)((DWORD **)((DWORD ***)(ArrayPtrS + 1 )))); printf ("ArrayPtrS[1] => %x \n" , PtrBB); DWORD **PtrAA = *((DWORD ***)(ArrayPtrS)+1 ); printf ("ArrayPtr[1] => %x \n" , PtrAA); DWORD Ref = *(DWORD *) (*((DWORD *)((DWORD **)((DWORD ***)(ArrayPtrS + 1 ))))); printf ("原始数值 ArrayPtrS[1] = %x \n" , Ref); system("pause" ); return 0 ; }
第二章:使用函数与指针 指针作为函数参数传递: 将指针直接作为函数参数传递,此时函数中接收到的就是数组的首地址.
#include <stdio.h> #include <stdlib.h> void MyPrintA (const char *String) { printf ("输出指针内容: %s \n" , String + 5 ); } void MyPrintB (const **String, int len) { for (int x = 0 ; x < len;x++) printf ("首地址: 0x%x 参数: %s \n" , *(String + x), String[x]); } int main (int argc, char * argv[]) { char *ptr = malloc (sizeof (char )* 100 ); memset (ptr, 0 , 100 ); strcpy (ptr, "hello lyshark" ); MyPrintA(ptr); char *String[] = { "admin" , "guest" , "lyshark" , "root" }; int len = sizeof (String) / sizeof (String[0 ]); MyPrintB(String, len); system("pause" ); return 0 ; }
指针作为函数返回值: 当一个函数执行结束后,会返回一些值,我们可以通过指针的方式间接返回.
#include <stdio.h> #include <stdlib.h> void AllocteSpace (char **Point) { char *ptr = malloc (100 ); memset (ptr, 0 , 100 ); strcpy (ptr, "hello lyshark" ); *Point = ptr; } int main (int argc, char * argv[]) { char *recv_ptr = NULL ; AllocteSpace(&recv_ptr); printf ("指针地址: %x --> 输出: %s \n" , &recv_ptr, recv_ptr); if (recv_ptr != NULL ) { free (recv_ptr); recv_ptr = NULL ; } system("pause" ); return 0 ; }
多维数组做函数参数: 将多维数组当作函数参数传递到函数内,并在函数内部进行强转,将指针强转为二维数组.
#include <iostream> #include <Windows.h> int GetArray (void * Pointer,int ArrayLen) { char (*ptr)[10 ]; ptr = (char (*)[10 ])Pointer; int count = 0 ; for (int x = 0 ; x < ArrayLen; x++) { if (strlen (ptr[x]) != 0 ) { count = count + 1 ; } } return count; } int main (int argc, char * argv[]) { char array [5 ][10 ] = {"zhangsan" ,"lisi" ,"wangwu" }; void * Pointer = &array [0 ][0 ]; int ref = GetArray(Pointer, 5 ); std ::cout << "元素个数: " << ref << std ::endl ; return 0 ; }
多级指针做函数参数: 如下代码中PrintArray()
函数传递了一个常量形式的二级指针作为参数,常量不可被修改.
#include <stdio.h> #include <stdlib.h> void PrintArray (const int **point) { for (int x = 0 ; x < 10 ; x++) printf ("地址: %x --> 数据: %d \n" , &point[x],*point[x]); } int main (int argc, char * argv[]) { int ary[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; int **pArray = malloc (sizeof (int *) * 10 ); for (int x = 0 ; x < 10 ; x++) *(pArray + x) = &ary[x]; PrintArray(pArray); system("pause" ); return 0 ; }
同理将多级指针进行封装,函数只需传递指针即可实现分配与释放,更易于使用.
#include <stdio.h> #include <stdlib.h> void allocateSpace (int **Point) { int * Array = malloc (sizeof (int )* 10 ); for (int x = 0 ; x < 10 ; x++) Array[x] = x; *Point = Array; } void PrintArray (int *Point) { for (int x = 0 ; x < 10 ; x++) printf ("地址: %x --> 数据: %d \n" , &Point[x],Point[x]); } void freeSpace (int **Point) { free (*Point); *Point = NULL ; Point = NULL ; } int main (int argc, char * argv[]) { int *pArray = NULL ; allocateSpace(&pArray); PrintArray(pArray); freeSpace(&pArray); system("pause" ); return 0 ; }
分配二级堆指针: 二级堆指针的含义是首先通过malloc开辟一级指针,然后在一级指针里面开辟二级指针.
#include <stdio.h> #include <stdlib.h> void PrintArray (const int **tmp) { for (int x = 0 ; x < 10 ; x++) printf ("%d " , *tmp[x]); } int main (int argc, char * argv[]) { int **pArray = malloc (sizeof (int *)* 10 ); for (int x = 0 ; x < 10 ; x++) { pArray[x] = malloc (4 ); *(pArray[x]) = x; } PrintArray(pArray); for (int x = 0 ; x < 10 ; x++) { if (pArray[x] != NULL ) { free (pArray[x]); pArray[x] = NULL ; } free (*pArray); *pArray = NULL ; } system("pause" ); return 0 ; }
上方我们可以很直观的看出二级指针的分配方式,其实字符串指针默认就是二级指针,只是看起来像是一级而已.
#include <stdio.h> #include <stdlib.h> int main (int argc, char * argv[]) { char *p[] = { "package" , "housing" , "pace" , "unleash" }; char **ptr = (char **)malloc (sizeof (char *) * 4 ); for (int x = 0 ; x < 4 ; x++) { ptr[x] = (char *)malloc (10 * sizeof (char )); sprintf (ptr[x], "%s" , p[x]); } for (int x = 0 ; x < 4 ; x++) { printf ("地址: %x --> 数据: %s \n" , &ptr,*ptr); ptr++; } system("pause" ); return 0 ; }
指向函数的指针(函数指针): 函数指针通常用于指向一个函数首地址,通过指针可以调用该函数.
#include <stdio.h> #include <string.h> int MyPrintA (int x,int y) { printf ("MyPrintA --> %d --> %d \n" , x, y); return 1 ; } int main (int argc, char * argv[]) { printf ("函数名入口: %d \n" , &MyPrintA); int *FuncAddr = (int *) &MyPrintA; int (*MyFunc)(int ,int ) = FuncAddr; int result = MyFunc(10 ,20 ); typedef int (Func_Type) (int , int ) ; Func_Type *pFunc = MyFunc; pFunc(100 , 200 ); (*pFunc)(1000 , 2000 ); typedef int (*Func_Ptr) (int , int ) ; Func_Ptr pFunc2 = MyFunc; pFunc2(10000 , 20000 ); int (*pfunc)(int , int ) = NULL ; pfunc = MyFunc; pfunc(100000 , 200000 ); printf ("函数名入口: %x \n" , &MyPrintA); int (*Print)(int , int ) = 0x4110e6 ; Print(1 , 2 ); system("pause" ); return 0 ; }
函数指针的参数传递: 将一个函数地址进行参数传递,实现动态的函数值传递,可作为函数定制使用.
#include <stdio.h> int add (int x, int y) { return x + y; }int sub (int x, int y) { return x - y; }void doLogic (int (*pFunc)(int , int ),int x,int y) { int result = pFunc(x, y); printf ("X与Y进行运算后的结果是: %d \n" , result); } int main (int argc, char * argv[]) { int (*ptr)(int , int ) = add; int result = ptr(10 , 20 ); printf ("两个数相加的结果是: %d \n" , result); doLogic(&sub, 100 , 10 ); doLogic(&add, 100 , 10 ); system("pause" ); return 0 ; }
函数指针传递数组: 除了传值以外,函数指针同样可以实现传递一个指针数组,并依次循环调用函数.
#include <stdio.h> int add (int x, int y) { int result = x + y; printf ("x + y => %d " , result); return result; } int sub (int x, int y) { int result = x - y; printf ("x - y => %d " , result); return result; } int main (int argc, char * argv[]) { int (*func_array[2 ])(int , int ); func_array[0 ] = add; func_array[1 ] = sub; for (int x = 0 ; x < 2 ; x++) { int z = func_array[x](100 , 20 ); printf (" -> %d \n" , z); } system("pause" ); return 0 ; }
函数指针绑定回调函数: 函数指针也可以实现绑定回调函数,当函数执行到指定位置时,执行回调输出一些数据.
#include <stdio.h> void Print_Array (void *Array, int eleSize, int len, void (*print)(void *)) { char *start = (char *)Array; for (int x = 0 ; x < len; ++x) { print(start + x * eleSize); } } void MyPrint (void *recv) { int *ptr = (int *)recv; printf ("回调函数 --> 输出地址: %x --> 数据: %d \n" , ptr,*ptr); } void MyPrintPerson (void *recv) { struct Person *stu = (struct Person *)recv; printf ("回调函数 --> 输出地址: %x \n" , stu); } int main (int argc, char * argv[]) { int arry[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; Print_Array(arry, sizeof (int ), 10 , MyPrint); struct Person { char name[64 ]; int age; }; struct Person stu [] = { { "admin" , 22 }, { "root" , 33 } }; Print_Array(stu, sizeof (struct Person), 2 , MyPrintPerson); system("pause" ); return 0 ; }