【保姆级讲解】C语言---指针精华
指针
1.1 内存地址的理解
计算机中的存储地址是以字节为单位的一片连续的存储空间,每一块空间都由自己唯一的一个地址编号(非负整数,从1开始自然增长),也叫字节编址。计算机中使用16进制来表示地址编号。
手机128G内存 128是128G字节空间(一个字节为8个位);
这里的0X01 0X02 0X03地址编号类比于生活:主卧床头柜从上第二个抽屉中有块手表
0X01 0X02 0X03(编号) =======主卧床头柜从上第二个抽屉(描述)=====地址值;
0x02地址空间中的数值(8个位空间中内容) == 等同于”手表”;
数据类型/变量/地址描述:
1.2 变量名、变量值和变量地址值
变量名:在定义变量后,编译器会在内存中开辟一个空间(空间大小是根据数据类型进行开辟int 4字节空间 double 8字节空间),变量名就是这个变量所占用内存单元的名字(编程人员提供标识 编译器进行阐述)。
变量内容(变量值):就是变量所占内存单元中所表示的数据。可以对变量进行读写操作,读变量就是从这个空间中将变量的值取出来,写变量就是把数值写入到这个变量所占用的内存单元中。
注意:变量内容仅是空间中数值; 10 =100;不能根据内容判定内存中唯一空间 A =100;由于A由编译器绑定了地址所以A能够确定内容中唯一的一块空间;
正在上传…重新上传取消
变量地址: C程序的变量都有自己的数据类型,编译器根据数据类型去开辟对应字节大小的字节空间。所谓的变量地址就是这个字节空间的首地址。
总结:
对于变量地址及变量名都能够确定唯一内存地址空间;对于变量内容不能确定唯一的内存地址空间;
能够确定唯一的内存地址空间的标识/地址,操作者即可以对该空间进行修改/读取内容操作;
1.3指针概述
指针也是一种数据类型(一种地址构造数据类型),32位系统下指针大小位4个字节(32位地址),8位系统下指针大小位3个字节(24位地址),64位系统下指针大小位8个字节(64位地址)。
指针作用:指针变量通常用来保存地址,通过指针可以访问保存在地址中的数据。
不同系统下指针大小区别:
32位系统(32位处理器32根地址线):能够访问2^32次方地址空间:为4GB空间;
采用地址值编号标识4GB空间:需要32位/4字节;
8位系统指针大小3字节; 256字节空间 16位单片机指针大小3字节;
64位系统(处理器64根地址线)寻址地址空间:2^64次方;指针大小为8字节;
总结:指针大小与数据类型无关,它与系统位数有关;
示例1:
Ubuntu16.04 32位系统 |
Ubuntu16.04 64 位系统 |
#include <stdio.h> int main() { int *A ; printf("%u\n",sizeof(A)); return 0; } |
#include <stdio.h> int main() { int *A ; printf("%u\n",sizeof(A)); return 0; } |
1.4 指针符号
对于指针是构造数据类型(基本数据类型+类似于”关键字”/”特殊的符号”);
&: 取地址符,用于取出指针指向的变量的地址。
*: 取内容符,把地址里的内容取出来(用于取出指针地址中的数值数据)
注意:对于&只能应用于变量名/数组名;不可以&常量值->&10错误;
*使用地址变量/数组能够把指向的空间内容取出;
1.5指针应用
1.5.1指针变量
指针变量定义:
在定义变量的时候,在变量名前加上“*”,表示这个变量是一个指针变量。使用“指针类型 变量名”这种格式来定义一个指针变量。
之前变量定义:数据类型 变量名;数据类型有大小影响开辟的空间大小;
现在指针变量定义:指针类型 变量名;指针类型大小(32为例)固定为4字节空间,影响访问内容读取(访问步长);
int *p;在定义语句中,*只是来说明这个变量是一个指针变量,没有实际的意思。
指针类型:使用基本数据类型和星号作为指针变量的指针类型,指针类型中的基本数据类型决定了指针变量所指向的变量的类型。
*: 在定义语句中,*只是来说明这个变量是一个指针变量,没有实际的意思。并不是变量名的一部分,也不是取内容符。
指针变量名:自定义标识符(命名规则同变量)。
指针变量名:可以为大小写英文字母、或者数字、下划线、美元$; 数字不能作为指针变量名开始;不能与关键字重名;
指针变量初始化:
在使用指针的时候,一定要进行初始化,避免野指针的出现(没有初始化的局部指针变量为野指针)。使用“指针类型 变量名 = 变量地址或NULL”的格式来对指针变量进行初始化。
注:在使用指针的时候,使用NULL来表示0,指向NULL的指针称之为空指针或指针指向为空。
#include <stdio.h> int main() { int *A ; //A在栈区 野指针 //栈区特点:变量值为随机值(垃圾值) printf("%u\n",sizeof(A)); printf("%p\n",A); //*A = 10; //就是对A指向的空间中赋值为10 请问该空间有吗?非法访问 //段错误 就是地址访问错误 在编译器变量表中没有该地值的空间开辟; //以上A为野指针 /***********************后期咱们使用******************************/ int B =10; int *PB =&B;//对于PB指针进行赋值为B空间首地址 printf("B:%p\t PB:%p\t*PB:%d\n",&B,PB,*PB); int *PC =NULL;//将PC指针指向为空 NULL==(void*)0; //避免野指针 //系统中0-4K只能读不能写; printf("PC:%p\n",PC); return 0; } |
指针变量应用
指针指向变量:
函数传参方面:
写swap(交换)函数:int A =5 int B =6; 编写一个函数实现对AB值进行交换;
#include <stdio.h> //写swap(交换)函数:int A =5 int B =6; 编写一个函数实现对AB值进行交换; void swap(int *num1 ,int *num2) { int temp = *num1; *num1 = *num2; *num2 = temp; } int main() { int A =5; int B =6; printf("A%d B:%d\n",A,B); //5 6 swap(&A,&B); printf("swap::A%d swap::B:%d\n",A,B); //王杰 56 浩林 65 return 0; } |
指向变量的指针
指针变量和普通变量之间的关系
- 指针变量用来指向(存储)普通变量的地址。à指针就是存储地址的;
- 可以通过指针变量来操作普通变量空间中的值。
- 一个变量可以有多个指针变量同时指向,但是一个指针变量每次只能指向一个普通变量。
指针:大小为4字节空间(只能存储一个地址)不能存储多个地址;
指针变量指向的地址(指针保存的地址)是一个变量(在程序运行的过程中可以改变指针的指向),普通变量的地址是一个常量(变量地址不可变)。
注:普通变量可以使用C语言运算符进行运算,但指针变量只能进行+、-、++、--运算,不能做*、/、%运算。
归结指针用法;优势;
1.5.2 指向数组的指针
指针和数组一样,都可以通过变量的下标来访问数组中的各个元素。指针变量+1,指针内存放的地址+n(n由指针指向空间类型决定)。使用“++”运算符来访问数组中的下一个元素,使用“--”运算符来访问数组中的上一个元素。
注:指针配合下标使用时,(例如p=num,p就相当于是数组名,跟数组用法一样)当数组的形式来使用;操作的是指针地址的时候,当指针的形式来用。
#include <stdio.h> int main() { //注:指针配合下标使用时,(例如p=num,p就相当于是数组名,跟数组用法一样)当数组的形式来使用;操作的是指针地址的时候,当指针的形式来用。 int buff[10]={1,2,3,4,5,6,7,8,9,10}; for(int i = 0; i < 10; i++) { printf("%d\n",buff[i]); } //通过指针也能够实现数组的访问 int *buffP=buff; for(int i =0; i < 10; i++) { printf("P:%d\n",buffP[i]);//当数组的形式来使用 // printf("PP:%d\n",*buffP++);//当指针的形式来用 //该题会出现基准值改变导致打印位置改变 } return 0; } |
#include <stdio.h> //对于连续的空间内容,尽量采用传地址方式解决 void function(int * buff_p) { for(int i =0;i < 10; i++) { //printf("%d\n",buff_p[i]); //将指针隐含转为数组名,通过下标访问 printf("%d\n",*buff_p++); //通过指针偏移访问++ } } int main() { int inputNumBuff[10]={1,2,3,4,5,6,7,8,9,10}; function(inputNumBuff); return 0; } |
1.5.3通过C库部分函数了解指针应用
本章节采用libc进行讲解:
/* Copy SRC to DEST. */ char * strcpy (char *dest, const char *src) //C库拷贝函数 { char c; char *s = (char *) src; const ptrdiff_t off = dest - s - 1; do { c = *s++; s[off] = c; } while (c != '\0'); return dest; } |
有时间请静心看一下呦;
1.5.4指向字符串的指针
- 指向字符串指针和字符串数组的区别
- 指针是一个地址变量,可以指向不同的字符串(指向不同的地址)。
- 数组是一个地址常量,只能用固定的地址来保存字符串(地址是个常量)。
1.5.5指向指针的指针
指向指针的指针也称为二级指针,一般是配置指针数组使用。一般情况下很少使用,使用的时候慎用。使用“指针类型 *变量名”的格式来定义一个二级指针。例如:int ** p。
#include <stdio.h> int main() { int A =10; int *PA =&A; int ** PPA= &PA; printf("&A:%p\tA:%d\n",&A,A); printf("&PA:%p\tPA:%p\n",&PA,PA); printf("PPA:%p\t*PPA:%p\t**PPA:%d\n",PPA,*PPA,**PPA); return 0; } 正在上传…重新上传取消 |
总结:函数传参方面 一级指针可以做到形参改变实参(普通变量)
二级指针可以做到形参改变实参(一级指针变量)
函数传参方面:要想改变一级指针所指向的位置需要通过二级指针进行修改;
#include <stdio.h> //总结:函数传参方面 一级指针可以做到形参改变实参(普通变量) // 二级指针可以做到形参改变实参(一级指针变量) void fun(char **a,char **b) { char *temp = *a; *a = *b; *b = temp; } int main() { char *PA = NULL; char *PB = NULL; char Src1[10]="hello"; char Src2[10]="123456789"; PA = Src1; PB = Src2; //置换地址操作 PA = Src1 PB = Src2 --> PA = Src2 PB =Src1; printf("PA:%s\n",PA); printf("PB:%s\n",PB); fun(&PA,&PB); printf(">PA:%s\n",PA); printf(">PB:%s\n",PB); return 0; } |
规律:函数传参 要想形参改变实参(普通变量)采用一级指针方式
要想形参改变实参(一级指针)采用二级指针方式;
- 二级指针与指针的关系:
二级指针是指向一级指针的地址(二级指针保存它指向的一级指针的地址)。
*二级指针是取一级指针指向的变量的地址(取得是一级指针保存的地址)。
**二级指针的内容是取一级指针指向的变量地址中的内容(取得是数值)。
#include <stdio.h> int main() { int A =10; int *PA =&A; int ** PPA= &PA; printf("&A:%p\tA:%d\n",&A,A); printf("&PA:%p\tPA:%p\n",&PA,PA); printf("PPA:%p\t*PPA:%p\t**PPA:%d\n",PPA,*PPA,**PPA); return 0; } |
课堂练习:
- 编写一个函数,使用指针方法实现在键盘上输入10个数,求输入的数的和。
#include <stdio.h> ) 编写一个函数,使用指针方法实现在键盘上输入10个数,求输入的数的和。 int inputNum(int * inputAddress) { int sum =0 ; for(int i = 0;i < 10 ; i++) { printf("请输入%d个数值\n",i); scanf("%d",inputAddress+i); sum+=*(inputAddress + i); } return sum; } int main() { int input[10]={0}; printf("sum:%d\n",inputNum(input)); return 0; } |
- 编写一个函数,实现在键盘上输入一个字符串,检测字符串是否为回文。
#include <stdio.h> #include <string.h> )2) 编写一个函数,实现在键盘上输入一个字符串,检测字符串是否为回文。 //函数类型 1为成功 0失败 int checkStringToHW(char * str) { int checkTrueFlage = 1; int stringLen = strlen(str);//长度 //判断 1234321 for(int i = 0; i < stringLen/2;i++) { if(*(str +i) != *(str + stringLen-1-i) ) { checkTrueFlage = 0; break; } } return checkTrueFlage; } int main() { char inputString[100]={0}; printf("请输入一串字符串\n"); gets(inputString); printf("%s\n",checkStringToHW(inputString)?"是回文":"不是回文"); return 0; } |
1.5.6 指针数组和数组指针
- 指针数组
指针数组本质上是一个数组(指针类型的数组),数组中的每一个元素的类型都是指针类型,使用的时候结合数组和指针规则使用。
指针数组格式:
指针类型 数组名[]; 例如:int * buff[10];为指针数组 本质还是数组 []优先级大于*优先级,本质还是数组; 每个元素所存放的为指针类型; |
实际中使用:
#include <stdio.h> #include <string.h> int main() { int A =10; int B =20; int C =30; int D =40; int E =50; //定义指针数组 int * numP[10]={&A,&B,&C,&D,&E,NULL,NULL,NULL,NULL,NULL}; printf("%d\t%d\t%d\t%d\t%d\n",*numP[0],*numP[1],*numP[2],*numP[3],*numP[4]); //存放文本常量区中的字符串首地址 char * stringBuff[] = {"1234","2345","3456","4567","5678"}; printf("%s\n",stringBuff[2]); return 0; } |
- 数组指针
数组指针的本质是一个指针(数组类型的指针),数组指针常用于访问二维数组时使用。使用“数据类型(*变量名)[数组长度]”的格式来定义一个数组指针。
使用场景: 数组指针常用于访问二维数组时;
数组指针格式:
数据类型 (*变量名)[数组长度]; 通过上面看:()优先级最高 指针 * 例如:int (*p)[4]; ()起来以后p先与*号进行结合,再与[]进行结合; Int:规定指向数组的类型; [4]:规定了指向的数组长度(列长度); |
注:数组指针又称为行指针;
#include <stdio.h> #include <string.h> int main() { int baseArr[3][4]={ {1,2,3,4}, {2,3,4,5}, {3,4,5,6} }; int (*p)[4] = baseArr; //数据 printf("baseArr[0][0]:%d\n",baseArr[0][0]); printf("baseArr[1][0]:%d\n",baseArr[1][0]); printf("baseArr[2][0]:%d\n",baseArr[2][0]); //地址 printf("&baseArr[0][0]:%p\n",&baseArr[0][0]); printf("&baseArr[1][0]:%p\n",&baseArr[1][0]); printf("&baseArr[2][0]:%p\n",&baseArr[2][0]); //数组指针 访问行地址 数组指针又称之为 行指针 p== printf("p:%p\n", p); printf("p+1:%p\n", p +1); printf("p+2:%p\n", p +2); //内容 获取每一行首个元素内容 printf("%d\n",**p); printf("%d\n",**(p+1)); printf("%d\n",**(p+2)); return 0; } |
1.5.7 指针函数和函数指针
- 指针函数
指针函数的本质上是一个函数(函数的类型是指针类型),函数的返回值(如果是局部变量(由于}后会释放会导致程序崩溃),该变量必须是静态局部变量,返回值是该静态局部变量的地址)也是一个指针或数组首地址。用法和函数一样,常用于返回数组以及指针变量。
函数类型:指针类型 int * fun(void) 该函数返回一个地址;
注:地址的返回只能返回静态变量的首地址、动态开辟(malloc)的地址,全局变量的地址、指针地址等,不能返回局部变量的地址。
需要将空间存活于访问之后;
#include <stdio.h> #include <string.h> //指针函数的本质上是一个函数(函数的类型是指针类型),函数的返回值(如果是局部变量,该变量必须是静态局部变量,返回值是该静态局部变量的地址)也是一个指针或数组首地址。用法和函数一样,常用于返回数组以及指针变量。 char * mystringcat(char * str1,char *str2) { int len = strlen(str1); int len2 = strlen(str2); strcpy(str1+len,str2); return str1; } int main() { char buff[100]="hello"; char buff2[100]="123456"; printf("%s\n",mystringcat(buff,buff2)); return 0; } |
#include <stdio.h> #include <string.h> //指针函数的本质上是一个函数(函数的类型是指针类型),函数的返回值(如果是局部变量,该变量必须是静态局部变量,返回值是该静态局部变量的地址)也是一个指针或数组首地址。用法和函数一样,常用于返回数组以及指针变量。 int * function(void) { static int A =100; return &A; } int main() { int* num = function(); printf("%d\n",*num); //A的生命周期远大于*num访问周期√ return 0; } |
- 函数指针
函数指针本质上是指针,指针指向的类型是一个函数类型,用法和指针一样。使用“函数类型 (*变量名)(形参列表) = (初始化内容)”的格式去定义一个函数指针。
格式: 函数类型 (*变量名)(形参列表) = (初始化内容) void (*functionP)() ; |
#include <stdio.h> #include <string.h> /********************************************************/ void functionA(void) { printf("void functionA(void)\n"); } void functionB(void) { printf("void functionB(void)\n"); } void functionC(void) { printf("void functionC(void)\n"); } /********************************************************/ int functionD(int num) { printf("int functionD(int num)\n"); } /********************************************************/ int functionE(int num,int num1) { printf("int functionE(int num,int num1)\n"); } int main() { //void (*fun_P)(void) = functionA; //函数指针 指针指向的类型是一个函数类型 指向函数的指针为函数指针 void (*fun_P)(void) = NULL; //函数指针 指针指向的类型是一个函数类型 指向函数的指针为函数指针 函数指针名称为fun_P 函数指针变量名fun_P //void (*fun_P)(void)只能指向函数类型为void 形参列表为void的函数 fun_P = functionA; fun_P(); fun_P = functionB; fun_P(); fun_P = functionC; fun_P(); /********************************************************/ //int (*fun_P)(int)只能指向函数类型为int 形参列表为一个int的函数 int (* fun_intp)(int) = NULL;//避免野指针 fun_intp = functionD; fun_intp(10); //运行 /********************************************************/ //int (*fun_P)(int)只能指向函数类型为int 形参列表为2个int的函数 int (*fun_intintp)(int,int) = NULL; fun_intintp = functionE; fun_intintp(10,20); return 0; } |
利用函数指针实现简易计算器:
#include <stdio.h> #include <string.h> /******************子函数***************************/ //加法 int add(int num1,int num2) { return num1+num2; } //减法 int sub(int num1,int num2) { return num1-num2; } //乘法 int mul(int num1,int num2) { return num1*num2; } //除法 int div(int num1,int num2) { return num1/num2; } int main() { //函数指针类型 int (*bc)(int,int) =NULL; int data1,data2; char op; printf("data1 op data2\n"); scanf("%d%c%d",&data1,&op,&data2); //通过switch语句实现计算器选择----函数指针方式 switch(op) { case '+': bc = add;break; case '-': bc = sub;break; case '*': bc = mul;break; case '/': bc = div;break; } printf("结果:%d\n",bc(data1,data2)); return 0; } |
例如:int (*p)(int a) = NULL; /* 定义一个函数指针p,指向为空 */
p:变量名
int(*)(int int):指针类型,int(*)(int int)是p的数据类型,指向一个整型函数,并且该函数有两个整型的形参。
注,四种类型的格式对比
指针数组 |
数据类型*变量名[数组长度]:char*x[10] |
数组指针 |
数据类型(*变量名)[数组长度]=(初始化内容) |
指针函数 |
数据类型*变量名[形参]:char*fun(void) |
函数指针 |
返回值类型(*变量名)(形参) =(初始化内容) |
1.5.8空类型指针以及指针四要素
- 空类型指针
空类型指针可以指向任何类型的元素的指针。
void *p:万能型指针
提高代码复用性:
#include <stdio.h> #include <string.h> //内存拷贝函数 void mymemcpy(int * desc,int * src,int size) { for(int i = 0; i< size; i++) { desc[i] = src[i];//*(desc +i ) = *(src +i) } } int main() { /*********************int*******************************/ int a[10]={1,2,3,4,5,6,7,8,9,10}; int b[10]={0}; mymemcpy(b,a,10); for(int i = 0; i < 10 ;i++) { printf("%d\n",b[i]); } /*********************char*******************************/ char char_a[10]={1,2,3,4,5,6,7,8,9,10}; char char_b[10]={0}; mymemcpy(char_b,char_a,10); //char* int*类型 有区别 读取内容 步长 for(int i = 0; i < 10 ;i++) { printf("%d\n",char_b[i]); } return 0; } |
好好看看 #include <stdio.h> #include <string.h> //内存拷贝函数 void mymemcpy(void * desc,void * src,int size) { char *src_p = (char *)src; char *desc_p = (char *)desc; for(int i = 0; i< size; i++) { desc_p[i] = src_p[i];//*(desc +i ) = *(src +i) } } int main() { /*********************int*******************************/ int a[10]={1,2,3,4,5,6,7,8,9,10}; int b[10]={0}; mymemcpy(b,a,40); for(int i = 0; i < 10 ;i++) { printf("%d\n",b[i]); } /*********************char*******************************/ char char_a[10]={1,2,3,4,5,6,7,8,9,10}; char char_b[10]={0}; mymemcpy(char_b,char_a,10); //char* int*类型 有区别 读取内容 步长 for(int i = 0; i < 10 ;i++) { printf("%d\n",char_b[i]); } return 0; } |
- 指针四要素
- 指针必须有类型,指针类型是声明指向对象的类型。
- 指针所指向的数据类型,决定了指针值(指针指向对象地址里的数值)的数据类型。
- 指针在使用时必须要有指向,避免野指针出现。
- 指针本身也占内存空间(指针本身也是一个变量)。
1.5.9 指针应用场合
- 当函数需要改变实参的时候,需要使用指针实现。
- 写一个函数,求字符串长度。
- 当函数需要传递一个数组时,需要使用指针实现。
- 当函数需要返回一个地址(例如函数需要返回数组)的时候,需要使用指针实现。
1.6 指针练习
基础作业:
- 编写一个函数用指针方法来实现求字符串的长度
#include <stdio.h> #include <string.h> /******************************************* 1.编写一个函数用指针方法来实现求字符串的长度 方法:地址差方式 ********************************************/ int getStringLen(char *src) { //借鉴上strcpy函数 C库中函数 char *offset = src; //偏移指针 while(*offset++ != '\0'); //先引用后加一 导致 结果多加1 return offset - src - 1; //结束地址减去起始地址 } int main() { printf("%u\n",getStringLen("hello")); } |
- 编写一个函数实现在键盘上输入两个字符串,比较输入的字符串是否一样
#include <stdio.h> #include <string.h> /******************************************* 2. 编写一个函数实现在键盘上输入两个字符串,比较输入的字符串是否一样 函数名称:int checkStringCmp(char *str1,char *str2) 函数参数:str1字符串1 str2字符串2 返 回 值:0表示不同 1表示相同 ********************************************/ int checkStringCmp(char *str1,char *str2) { int returnval = 1; //先比较长度 长度不一致 会导致字符串不同 int strLen1 = strlen(str1); int strLen2 = strlen(str2); if(strLen1 == strLen2) { while(*str1 != '\0') { if(*str1 != *str2) { returnval =0; break; } str1++; str2++; } } else { returnval = 0; } return returnval; } int main() { char readBuff1[100]={0}; char readBuff2[100]={0}; printf("请输入第1串字符串\n"); gets(readBuff1); printf("请输入第2串字符串\n"); gets(readBuff2); printf("%s\n",checkStringCmp(readBuff1,readBuff2)?"相同":"不相同"); } |
- 编写一个名为sumnarrays()的函数,它接受两个数组作为参数,长度为4将两个数组中的所有值相加,并返回得到的结果。
#include <stdio.h> #include <string.h> /******************************************* 3.编写一个名为sumnarrays()的函数, 它接受两个数组作为参数,长度为4将两个数组中的所有值相加, 并返回得到的结果。 ********************************************/ int sumnarrays(int * numbuff1,int * numbuff2,int len) { int sum = 0; for(int i =0;i < len ;i++) { sum +=*(numbuff1 + i)+*(numbuff2 + i); } return sum; } int main() { int buff1[4]={1,2,3,4}; int buff2[4]={2,2,2,2}; printf("%d\n",sumnarrays(buff1,buff2,4)); } |
- 编写一个名为addarrays()的函数,它接受三个长度相同的数组,两个数组中对应的元素相加,并将结果放到第三个数组中。
#include <stdio.h> #include <string.h> /******************************************* 4.编写一个名为addarrays()的函数,它接受三个长度相同的数组, 两个数组中对应的元素相加,并将结果放到第三个数组中。 ********************************************/ void addarrays(int * src1,int * src2,int *desc,int len) { int * offset = desc; for(int i = 0; i < len ;i++) { *(offset+i) = *(src1+i) + *(src2+i); } } int main() { int buff1[4]={1,2,3,4}; int buff2[4]={2,2,2,2}; int desc[4]={0}; addarrays(buff1,buff2,desc,4); for(int i =0; i < 4 ;i++) { printf("%d\t",desc[i]); } } |
- 写一个函数实现在一个字符串中查找键盘上输入的字符,并且返回这个字符的地址。Qwertyuiop
#include <stdio.h> #include <string.h> /******************************************* 5. 写一个函数实现在一个字符串中查找键盘上输入的字符, 并且返回这个字符的地址。Qwertyuiop 是相对地址 相关字符在字符串内 位置 ********************************************/ int getStringAddress(char * str,char ch ) { int len = strlen(str); int offset =0; for(int i =0; i < len;i++) { offset++; if(*(str+i) == ch) { break; } if(i == len -1) return 0; } return offset; } int main() { printf("%d\n",getStringAddress("Qwertyuiop",'Q')); } |
提高作业:
- 写一个函数:对字符数组的内容进行排序。提示:冒泡排序。
#include <stdio.h> #include <string.h> /******************************************* 5.6.写一个函数:对字符数组的内容进行排序。提示:冒泡排序。 ********************************************/ char * function(char * str) { if(*str == '\0') return NULL; else if((*str != '\0')&&((*(str+1) == '\0'))) return str; else if(str == NULL) return NULL; else { int len = strlen(str); for(int i = 0; i < len -1; i++) { for(int j =0; j< len-1-i;j++) { char ch; if(*(str+j) > *(str+j+1)) { ch = *(str+j); *(str+j) = *(str+j+1); *(str+j+1) = ch; } } } return str; } } int main() { char buff[100]="987654321"; printf("%s\n",function(buff)); //printf("%s\n",function("987654321"));//在文本常量区 只能读不能写 } |
扩展作业:
- 写一个函数实现字符串的连接(strcat)。 "hello" "world"把两个字符串连接成一个字符串,并且返回连接好的字符串的首地址。
#include <stdio.h> #include <string.h> /******************************************* 7.写一个函数实现字符串的连接(strcat)。 "hello" "world"把两个字符串连接成一个字符串,并且返回连接好的字符串的首地址。 想学习strcpy操作 小端存储 ********************************************/ char * mystrcat(char * str1,char *str2) { int i =0; //先忽略掉空间不足 int len = strlen(str1); while(*str2 !='\0') { *(str1+len+i) = *(str2+i); i++; } return str1; } int main() { char buff[100]="hello"; char buff2[100]="world"; printf("%s\n",mystrcat(buff,buff2)); } |
【保姆级讲解】C语言---指针精华相关推荐
- STM32 FSMC/FMC原理保姆级讲解(二)
上一话我们说了FSMC的基本原理及控制逻辑,这一讲我们来说下FSMC如何通过HAL库来进行配置,及具体参数 STM32 FSMC/FMC原理保姆级讲解(一) FSMC的初始化 在使用SRAM之前,我们 ...
- STM32 FSMC/FMC原理保姆级讲解(一)
FSMC通俗讲解 FSMC 框图 FMC引脚说明 FMC地址映射 FSMC不同位宽操作 FSMC寄存器 FSMC时钟 FSMC 四种模式 FSMC参数设置 FSMC 控制异步 NOR FLASH 的时 ...
- 保姆级讲解 Stable Diffusion
文章目录 整体代码 unet解析 self.input_blocks middle_blocks self.output_blocks 保姆级讲解 Stable Diffusion: https:// ...
- 教你手写DMA传输数据(看完这篇你就会手动写啦,保姆级讲解)---- 2020.3.31
关于DMA与串口原理方面的文章: 嵌入式stm32 复习(工作用)- USART(串口)通信原理知识 2020.3.23 添加链接描述 教你手写串口收发数据(看完这篇你就会手动写啦,保姆级讲解)--- ...
- c语言指针题讲解,C语言指针经典练习题-及答案讲解.doc
C语言指针练习题及答案 一. 1. 变量的指针,其含义是指该变量的____. a)值 b)地址 c)名 d)一个标志.若有语句int *point,a=4;和point=&a;下面均代表地址的 ...
- 【保姆级讲解】C语言---函数精华面试题荟
学不过瘾?配套更多面试题讲解视频请移步下方直通车https://www.bilibili.com/video/BV1E34y1a7WP/ 1.写一个函数实现检测一个正整数是否是回数,如果是,返回1,不 ...
- 【保姆级讲解】C语言---预编译处理精华
预编译处理 1.1预编译处理概述 预编译处理也称为编译预处理,是在程序正式编译之前需要进行的前期编译处理阶段.主要作用是向编译器传递信息.以井号("#")开头的命令都是编译预处理命 ...
- C语言实现通讯录代码详解(保姆级讲解)
引言 我们常说去用C语言去完成一些项目,实现一些我们想要的功能和搭建一个简单的平台或者完成一个小游戏的代码编写.我想说的是无论你想要用C语言去实现什么,首先得确定你需要实现的哪些些功能,然后通过自己对 ...
- C语言(APL指令)对mysql数据库的操作-----连接、读取、写入、修改、删除(保姆级讲解)
目录 前言: C语言操作mysql前的准备工作 1.C语言连接mysql数据库 函数介绍 (1)mysql_ini() 函数 (2)mysql_library_init()函数 (3)mysql_re ...
最新文章
- 金蝶 K/3 Cloud 服务端控件编程模型
- TensorFlow Wide And Deep 模型详解与应用 TensorFlow Wide-And-Deep 阅读344 作者简介:汪剑,现在在出门问问负责推荐与个性化。曾在微软雅虎工作,
- 高级concurrent包
- linux SHELL脚本编程
- 使用ETag识别ajax,如何使用jQuery AJAX请求访问ETag头?
- IDEA开发WebService遇到的问题和SOAPUI工具的使用
- 关于MVC打印问题,打印指定的内容
- Linux经常使用到的操作
- 腾讯IM : 如何替换String 表情库
- 第四章需求分析与设计工具
- MYSQL建表语句转换成oracle建表语句
- win7 IE11浏览器怎么改成中文
- 推贴B2B/B2C订货商城系统 V3.0版
- 第六篇:uniapp的rpx响应式px样式
- 罗振宇解读《今日简史》:21个议题就是21个千亿美金的机会
- 我们说运营,到底是在说运营什么?
- SpringBoot 接口数据加解密实战!
- java虚拟机学习笔记之垃圾收集(上)
- 中小企业OA管理系统(微鳄OA私有化部署)
- 什么是系统漏洞,该如何处理?