打印
[应用方案]

strlen掉坑实例

[复制链接]
142|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sanfuzi|  楼主 | 2025-2-17 21:46 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
[color=rgba(0, 0, 0, 0.9)]  就先贴上一个掉坑的例子,然后在跟大家总结分享下原因和避坑指南:
编码目标:
[color=rgba(0, 0, 0, 0.9)]
[color=rgba(0, 0, 0, 0.9)]    根据字符串起点打印不同偏移(Offset)到结尾的字符串,如果Offset为负数就向前移动并打印到字符串末尾。
掉坑示例:
1#include <stdio.h>
2#include <string.h>
3/***************************************
4 * Fuction:sGetStr
5 * Decri  :打印相应位置到末尾的字符串
6 * Author :(欢迎关注公众号:最后一个bug)
7 ***************************************/

8int sGetStr(const char * str,int offset)
9{
10   if(offset > strlen(str))
11    {
12        printf("offset Over Error!!\n");
13    }
14    else
15    {
16        printf("%s\n",str + offset);
17    }
18}
19/***************************************
20 * Fuction:main
21 * Decri  :不同起点位置的字符串打印
22 * Author :(欢迎关注公众号:最后一个bug)
23 ***************************************/

24int main(int argc, char *argv[]) {
25
26    char * pSrstr = "0123456789";
27
28    sGetStr(pSrstr + 5,0);
29    sGetStr(pSrstr + 5,-2);
30
31    printf("欢迎关注公众号:最后一个bug\n");
32    return 0;
33}


  • 第一次打印能够成功,而第二次采用负数Offset打印直接比较失败,很明显Offset为负数却大于了strlen返回值,基本上我们肯定strlen肯定是正数,那为啥会失败呢?我们还得查查strlen的函数原型。


3、size_t分析
[color=rgba(0, 0, 0, 0.9)]    于是找来了一个strlen的函数声明:
[color=rgba(0, 0, 0, 0.9)]
[color=rgba(0, 0, 0, 0.9)]    通过上面的声明我们了解到size_t是一个与系统有关的定义类型,系统为了增强可移植性等等会进行不同的处理,到这里应该会有点想法,难道这个size_t是一个无符号类型?
[color=rgba(0, 0, 0, 0.9)]    因为之前我们也说过整形数据的提升问题 ,如果unsigned int与int进行运算会统一提升为无符号来处理,这样也会导致出现上面的结果。

[color=rgba(0, 0, 0, 0.9)]    得找找size_t的具体实现,通过查找C标准库了解到,size_t是一个无符号的整形类型,如下图所示:
[color=rgba(0, 0, 0, 0.9)]
[color=rgba(0, 0, 0, 0.9)]    总感觉说明虚了一点,还是上代码比较实在点,于是bug菌找来了一个具体实现:

[color=rgba(0, 0, 0, 0.9)]
[color=rgba(0, 0, 0, 0.9)]    上图可以看到size_t根据系统位数不同,分别由unsigned int和unsigned long这样的无符号类型来实现,所以与我们的猜测还是相符合的。
[color=rgba(0, 0, 0, 0.9)]    如果还想进一步深究,请看汇编吧!!
处理办法:
[color=rgba(0, 0, 0, 0.9)]    处理办法其实挺多,可以把strlen函数返回值强制类型转化为一个有符号类型,然后再进行有符号类型比较;如果有符号数为负数也可以单独判断符号后处理。
[color=rgba(0, 0, 0, 0.9)]    下面我们就简单的强制类型转化一下看一下结果,之前的代码做如下修改:
1/***************************************
2 * Fuction:sGetStr
3 * Decri  :打印相应位置到末尾的字符串
4 * Author :(欢迎关注公众号:最后一个bug)
5 ***************************************/

6int sGetStr(const char * str,int offset)
7{
8   if(offset > (int)strlen(str)) //强制转化为有符号
9    {
10        printf("offset Over Error!!\n");
11    }
12    else
13    {
14        printf("%s\n",str+offset);
15    }
16}


  • 上图的输出我们获得了正确的结果。
  • 那么对于平时喜欢使用size_t类型或者是一些与size_t有关的标准函数可也要注意了,不然一不小心又掉到坑里去了!


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

29

主题

3153

帖子

1

粉丝