ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

指针(3):strlen的模拟实现和传址调用

指针(3):strlen的模拟实现和传址调用 指针3strlen的模拟实现和传址调用1.strlen的模拟实现1.1 streln的介绍1.2 strlen的模拟实现1.3 注意1.4 补充2.传址调用1.strlen的模拟实现1.1 streln的介绍库函数strlen的功能是求字符串的长度统计的是字符串中\0之前的字符的个数函数原型如下size_tstrlen(constchar*str);参数str接收⼀个字符串的起始地址然后开始统计字符串中 \0 之前的字符个数最终返回⻓度。strlen的运用#includestdio.h#includestring.hintmain(){intretstrlen(abcdef);printf(%d,ret);return0;}字符串“abcdef”在内存中实际存储的是a b c d e f \0共7个字节strlen只统计\0之前字符的数量因此输出结果为6。1.2 strlen的模拟实现根据上面对strlen函数原型的分析我们可以得知如果要模拟实现只要从起始地址开始向后逐个字符的遍历只要不是 \0 字符计数器就1这样直到 \0 就停⽌。接下来就让我们来完成strlen模拟实现的代码#includestdio.hsize_tmy_strlen(constchar*str){size_tcount0;while(*str){str;count;}returncount;}intmain(){size_tretmy_strlen(abcdef);printf(%zu\n,ret);return0;}首先将 “abcdef” 传到函数my_strlen中设置一个计数器count用来统计该字符串\0之前的字符的个数通过while循环遍历该字符串\0之前的字符每循环一次指针向后移动一位并且使得计数器count加一遍历完成后返回count函数模拟完成1.3 注意通过观察我们可以发现模拟函数实现时我们定义的用来接收my_strlen的ret的类型为size_t无符号整数类型而上面我们在运用strlen时用来接收其返回值时用的ret的类型为int但最后输出结果都正确这是为什么呢。这是因为字符串“abcdef”中字符数量太小用int来接收也足够当字符数量够大时用int接收就会出现错误所以最好是使用size_t 和 %zu来接收和打印当然在字符串比较小的时候也可以用int 和 %d来接收和打印。此外还有一个需要注意的点由于strlen的返回值是无符号整数因此两个strlen相减是不能得到负数的看下面这个例子if(strlen(hi)-strlen(hello)0)在这个例子中看似strlen(“hi”)得到数是2strlen(“hello”)得到的数是42 - 4 0,但是strlen返回值是size_t不存在负数只用正数因此strlen(“hi”) - strlen(“hello”所得到的值是一个很大的无符号正数因此这个式子永远大于0.1.4 补充根据之前章节里面所提到的指针-指针我们可以用另一种方式来实现strlen的模拟实现即首先记录指针的起始位置然后遍历字符串得到指针结束时的位置用结束指针-起始指针即可得到字符的数量。#includestdio.hsize_tmy_strlen(constchar*str){constchar*startstr;while(*str){str;}returnstr-start;}intmain(){size_tretmy_strlen(abcdef);printf(%zu\n,ret);return0;}注意指针相减得到的数字是有符号整数类型但return时会将其隐式转化size_t类型因此无需进行强制类型转化。2.传址调用我们学习指针是为了解决问题那么有哪些问题是只有指针才能解决的呢我们来看这样一个问题写一个函数交换两个整型变量的值。经过一番思考我们可能会写出这样的代码#includestdio.hvoidswap(intx,inty){intc0;cx;xy;yc;}intmain(){inta5;intb3;swap(a,b);printf(%d %d,a,b);return0;}让我们运行起来看看是否能够达到目的我们发现这并没有产生交换的后果这是为什么呢让我们来通过调试观察一下。我们发现在main函数内部创建了变量a b他们的地址分别为0x000000026dc6ff6c4 和 0x000000026dc6ff6e4而在调用swap函数时我们将 a 和 b 传递给swap函数swap函数在函数内部创建了形参x 和 y用来接收a 和 b的值但是x的地址是0x000000026dc6ff6a0y的地址是0x000000026dc6ff6a8x和y确实接收到了a和b的值不过x的地址和a的地址不⼀样y的地址和b的地址不⼀样相当于x和y是独⽴的空间而我们又知道数据都是存储在地址所对应的内存单元当中他们的地址不同因此他们所对应的内存单元也就不同那么在swap函数内部交换x和y的值⾃然不会影响a和b当swap函数调⽤结束后回到main函数a和b的值没法交换。这就是传值调⽤因此我们可以得出结论实参传递给形参的时候形参会单独创建⼀份临时空间来接收实参对形参的修改不影响实参。因此swap失败了那我们该怎么办呢其实只需要将a和b的地址传递给swap函数让swap函数通过地址间接的操作a和b的值这样就能够达到交换a和b的值的功能了。#includestdio.hvoidswap(int*x,int*y){intc0;c*x;*x*y;*yc;}intmain(){inta5;intb3;swap(a,b);printf(%d %d,a,b);return0;}由此我们看到代码成功的完成了任务这⾥调⽤swap函数的时候是将变量的地址传递给了函数这种函数调⽤⽅式叫传址调⽤传址调⽤可以让函数和主调函数之间建⽴真正的联系在函数内部可以修改主调函数中的变量所以未来函数中只是需要主调函数中的变量值来实现计算就可以采⽤传值调⽤。如果函数内部要修改主调函数中的变量的值就需要传址调⽤。
返回列表