数组指针
#include <stdio.h> int getTheData(int (*p)[4],int hang,int lie)//(*p)[4]是数组指针 { int data; data = *(*(p+hang)+lie);//将对应数组中的值找出来 return data; //return p[hang][lie];//同理 将对应数组中的值找出来 } void tipsInputHangLie(int *pm, int *pn)//形参中的变量类型要与实参中相同,都是int { printf("输入行列值:\n"); scanf("%d%d",pm,pn);//指针就是地址,对相应的地址进行操作 puts("done!"); } //arr,arr[0] int main() { int arr[3][4] = {{11,22,33,44},{12,13,15,16},{22,66,77,88}};//arr+ int ihang,ilie; int data; //1. 提示用户输入行列值 tipsInputHangLie(&ihang,&ilie);//对地址进行操作,所以函数中的操作能改变ihang和ilie的值 //2. 找出对应行列值的那个数 data = getTheData(arr,ihang,ilie);//arr是数组的地址,也就是指针 //3. 打印出来 printf("%d行%d列的值是%d\n",ihang,ilie,data); }
输出内容
函数指针
回掉函数的底层逻辑就是函数指针
#include <stdio.h> #include <stdlib.h> int getMax(int data1, int data2) { return data1>data2 ? data1:data2; } int getMin(int data1, int data2) { return data1<data2 ? data1:data2; } int getSum(int data1, int data2) { return data1+data2; } int dataHandler(int data1, int data2, int (*pfunc)(int, int ))//第三个形参是函数指针,函数指针中对类型有要求,形参名可省略 { int ret; ret = (*pfunc)(data1,data2);//调取函数,求得返回值 return ret; } int main() { int a = 10; int b = 20; int cmd; int ret; int (*pfunc)(int , int ); printf("请输入1(取大值),2(取小值),或者3(求和)\n"); scanf("%d",&cmd); switch(cmd){ case 1: pfunc = getMax;//对地址进行了更改,也就变化了对应的值 break; case 2: pfunc = getMin; break; case 3: pfunc = getSum; break; default: printf("输入错误!@输入1(取大值),2(取小值),或者3(求和)\n"); exit(-1);//异常退出 break; } ret = dataHandler(a,b,pfunc);//pfunc获取了对应的函数名,第三个实参pfunc是函数指针的地址 printf("ret = %d\n",ret); return 0; }
输出内容
函数指针数组
#include <stdio.h> #include <stdlib.h> int getMax(int data1, int data2) { return data1>data2 ? data1:data2; } int getMin(int data1, int data2) { return data1<data2 ? data1:data2; } int getSum(int data1, int data2) { return data1+data2; } int main() { int a = 10; int b = 20; int ret; int (*pfunc[3])(int , int )={ getMin, getMax, getSum};//函数指针数组!初始化,将数组中的值(这个值是个地址,也就是指针,这个指针是个函数指针,将三个函数地址放在数组里) for(int i=0;i<3;i++){ ret = (*pfunc[i])(a,b);//遍历数组中的三个函数指针,获取返回值 printf("ret = %d\n",ret); } return 0; }
输出内容
函数指针
#include <stdio.h> int* getPosPerson(int pos, int (*pstu)[4])//函数指针,返回指针的函数 { int *p; p = (int *)(pstu+pos);//二维数组地址+输入的数就是对应的数组值,然后赋值给P return p; } int main() { int scores[3][4]={ {55,66,77,88},//学生1 {66,55,99,100},//学生2 {11,22,33,59},//学生3 }; int *ppos; int pos; printf("请输入你需要看的学生号数:0,1,2\n"); scanf("%d",&pos); ppos = getPosPerson(pos, scores);//获取对应数组的地址 for(int i=0;i<4;i++){//将小数组里面的值进行遍历出来输出 printf("%d ",*ppos++);//++代表偏移一个int整形的字节数 } return 0; }
输出内容
二级指针
#include <stdio.h> void getPosPerson(int pos, int (*pstu)[4],int **ppos)//函数指针,返回指针的函数 { *ppos = (int *)(pstu+pos);//用二级指针的目的是直接修改了MAIN函数中的ppos的值 } int main() { int scores[3][4]={ {55,66,77,88}, {66,55,99,100}, {11,22,33,59}, }; int *ppos; int pos; printf("请输入你需要看的学生号数:0,1,2\n"); scanf("%d",&pos); getPosPerson(pos, scores,&ppos); for(int i=0;i<4;i++){ printf("%d ",*ppos++); } return 0; }
输出内容
在新版的C语言中出现了断言函数assert
assert() 的用法很简单,我们只要传入一个表达式,它会计算这个表达式的结果:
如果表达式的结果为“假”,assert() 会打印出断言失败的信息,并调用 abort() 函数终止程序的执行;
如果表达式的结果为“真”,assert() 就什么也不做,程序继续往后执行。
#include <stdio.h> #include <assert.h> char* myStrcpy(char *des, char *src) { //assert 的作用是现计算表达式 expression ,如果其值为假(即为0), //那么它先向 stderr 打印一条出错信息,然后通过调用 abort 来终止程序运行 assert(des != NULL && src != NULL);//断言 char *bak = des; while( *src != '\0'){ *des = *src; des++; src++; } *des = '\0'; return bak; } char* myStrcpy2(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0'){ *des++ = *src++; } *des = '\0'; return bak; } char* myStrcpy3(char *des, char *src) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( (*des++ = *src++) != '\0'); *des = '\0'; return bak; } char* myStrncpy(char *des, char *src, int count) { if(des == NULL || src == NULL){ return NULL; } char *bak = des; while( *src != '\0' && count>0){ *des++ = *src++; count--; } if(count > 0){ while(count > 0){ count--; *des++ = '\0'; } return des; } *des = '\0'; return bak; } int main() { char str[128] = {'\0'}; char *pstr = NULL; char a = 'm'; char b; if((b=a) == 'm'){ printf("ok\n"); } char *p = "chenlichen handsome"; myStrcpy(pstr, p);//这么一拷贝显然是假,P不为NULL,所以打印错误LOG信息,结束程序 puts(str); return 0; }
输出结果:
ok Assertion failed: des != NULL && src != NULL, file 1.c, line 7
字符串拼接函数strcat
#include <stdio.h> #include <string.h> int main() { char str[128] = "liuzhihao"; char *p = "xiaohao"; char *p2; p2 = strcat(str,p); puts(str); puts(p2); return 0; }
输出结果
liuzhihaoxiaohao liuzhihaoxiaohao
多种写法实现strcat
#include <stdio.h> #include <string.h> #include <assert.h> char* myStrcat(char *des, char *src) { assert( des!=NULL && src!=NULL); char *bak = des; while(*des){ des++; } while((*des++ = *src++) != '\0'); *des = '\0'; return bak; } char* myStrcat2(char *des, char *src) { char *bak = des; strcpy(des+strlen(des),src); return bak; } char* myStrcat3(char *des, char *src) { assert( des!=NULL && src!=NULL); char *bak = des; for(;*des!='\0';des++); while((*des++ = *src++) != '\0'); *des = '\0'; return bak; } int main() { char str[128] = "liuzhihao"; char *p2; char *p = " xiaohao"; p2 = myStrcat(str,p); //p2 = strcat(str,p); puts(str); //puts(p2); return 0; }
strcmp函数
#include <stdio.h> #include <string.h> #include <assert.h> int myStrcmp(char *str1, char *str2) { int ret = 0; int n_str1 = 0; int n_str2 = 0; char *bakStr1 = str1; char *bakStr2 = str2; while( *str1 && *str2 && (*str1 == *str2)){ str1++; str2++; } if(*str1 || *str2){ str1 = bakStr1; str2 = bakStr2; while(*str1){ n_str1 += *str1; str1++; } while(*str2){ n_str2 += *str2; str2++; } } ret = n_str1 - n_str2; if(ret < 0){ ret = -1; } if(ret > 0){ ret = 1; } return ret; } int main() { char *p1 = "chmnlichend"; char *p2 = "chenlzchend"; int ret = myStrcmp(p1,p2);//-1 1 0 int ret = strcmp(p1,p2);//-1 1 0 if(ret == 0){ puts("相同"); } printf("RET = %d\n",ret); return 0; }
结构体指针
#include <stdio.h> struct Test { int idata; char cdata; }; int main() { int var = 20; int *ip; ip = &var; printf("ip%d\n", *ip);//这里是用*号是因为,变量就是指针,也就是地址 struct Test t1 = {10, 'c'}; //1. 类型 2.名 3.值 4.地址 struct Test *ps; ps = &t1; printf("t1的idata=%d\n",t1.idata);//变量名访问,用点运算符 printf("t1的idata=%d\n",ps->idata);//这里ps->idata的前面没用*,因为结构体成员是int型的,所以不用*,取决于结构体成员的类型,用.还是用->取决于结构体是指针还是普通变量 return 0; }