免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7591 | 回复: 10
打印 上一主题 下一主题

[C] strlen 的返回值为何是无符号值而不是有符号值? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-02-26 11:39 |只看该作者 |倒序浏览
我的理解是,strlen的功能是得到字符数,也就是一个绝对值,无符号值得范围是 0-65535,总是个正值,
  有符号值是 -32767 至 + 32768 ;  65535 大于 32768 ,范围更大。

          而返回值用无符号值不好的地方就是 如果再 if 表达式中利用strlen 返回值进行逻辑判断会出现不可预料的结果。


                                       以上理解对吗? 您还有更好的解释吗?   谢谢!!!

论坛徽章:
0
2 [报告]
发表于 2009-02-26 11:49 |只看该作者
strlen返回的值肯定是>=0,而至于if中逻辑判断会出现不可预料的错误一说,我没明白。。。

论坛徽章:
0
3 [报告]
发表于 2009-02-26 11:58 |只看该作者
原帖由 alexhappy 于 2009-2-26 11:49 发表
strlen返回的值肯定是>=0,而至于if中逻辑判断会出现不可预料的错误一说,我没明白。。。



看C和指针书 P176 警告

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
4 [报告]
发表于 2009-02-26 12:01 |只看该作者
原帖由 alexhappy 于 2009-2-26 11:49 发表
strlen返回的值肯定是>=0,而至于if中逻辑判断会出现不可预料的错误一说,我没明白。。。


大概他的意思是说,一般人都习惯声明int valid_len了,所以当使用if(valid_len != strlen(...))时会出现有符号无符号数不匹配问题(这种问题有的编译器不会给出警告)。

论坛徽章:
0
5 [报告]
发表于 2009-02-26 12:06 |只看该作者
原帖由 std_linux 于 2009-2-26 11:39 发表
我的理解是,strlen的功能是得到字符数,也就是一个绝对值,无符号值得范围是 0-65535,总是个正值,
  有符号值是 -32767 至 + 32768 ;  65535 大于 32768 ,范围更大。

          而返回值用无符号值不好 ...



事实证明,楼主的猜测是错误的

下面是我实际测试的例子,有同样疑问者可以各自测试一下

  1. [net@localhost tmp]$ cat k.c

  2. #include <stdio.h>
  3. int main ()
  4. {
  5.         int i=0;
  6.         int j=-1;
  7.         unsigned int m=0;
  8.         unsigned int n=0;
  9.         n=j;

  10.         printf("%d,%u\n",j,n);
  11.         if(n>0)
  12.         {
  13.                 printf("n > 0\n");
  14.         }
  15.         if(n>m)
  16.         {
  17.                 printf("n > m\n");
  18.         }
  19. }
  20. [net@localhost tmp]$ gcc k.c ;./a.out
  21. -1,4294967295
  22. n > 0
  23. n > m
  24. [net@localhost tmp]$
复制代码

  1. [net@localhost tmp]$ gcc --version
  2. gcc (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7)
  3. Copyright (C) 2008 Free Software Foundation, Inc.
  4. This is free software; see the source for copying conditions.  There is NO
  5. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
复制代码

论坛徽章:
0
6 [报告]
发表于 2009-02-26 12:17 |只看该作者
原帖由 net_robber 于 2009-2-26 12:06 发表



事实证明,楼主的猜测是错误的

下面是我实际测试的例子,有同样疑问者可以各自测试一下

[net@localhost tmp]$ cat k.c

#include
int main ()
{
        int i=0;
        int j=-1;
        unsigned int m=0;
...


不好意思,每看明白,能否指点一下。谢谢!!!

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
7 [报告]
发表于 2009-02-26 14:40 |只看该作者
int main()
{
int i = -1;
unsigned j = 0;
if (i > j) printf("error.\n");
if (j > i) printf("ok.\n");
}

编译时警告: warning: comparison between signed and unsigned integer expressions

程序运行输出: error.

编译器是RHEL 5.3自带的gcc 4.1.2 20080704


————————————————-
即便一些混用有符号/无符号的比较能得到正确结果,也不说明这就是对的。因为这两个本来就属于不同的类型,有不同的取值范围;至于比较的细节,不同cpu、不同编译器都可能不同——所以gcc才会为这类表达式生成警告。

当然,一般情况下,字符串不超长时,即便不理睬这类警告,程序也是能得到正确结果的。但从根本上说,这种写法就是错误,换个场合就可能出问题。

论坛徽章:
0
8 [报告]
发表于 2009-02-26 14:46 |只看该作者
原帖由 shan_ghost 于 2009-2-26 14:40 发表
int main()
{
int i = -1;
unsigned j = 0;
if (i > j) printf("error.\n");
if (j > i) printf("ok.\n");
}

编译时警告: warning: comparison between signed and unsigned integer expressions

程 ...



针对你的代码,我的测试结果如下
  1. [net@localhost tmp]$ cat x.c
  2. #include <stdio.h>
  3. int main()
  4. {
  5.         int i = -1;
  6.         unsigned j = 0;
  7.         if (i > j) printf("error.\n");
  8.         if (j > i) printf("ok.\n");
  9. }
  10. [net@localhost tmp]$ gcc x.c ; ./a.out
  11. error.
  12. [net@localhost tmp]$ gcc --version
  13. gcc (GCC) 4.3.2 20081105 (Red Hat 4.3.2-7)
  14. Copyright (C) 2008 Free Software Foundation, Inc.
  15. This is free software; see the source for copying conditions.  There is NO
  16. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

  17. [net@localhost tmp]$
复制代码

论坛徽章:
0
9 [报告]
发表于 2009-02-26 14:49 |只看该作者
这个问题无非就是自动类型转换的默认转换方向的问题

或者直接说就是 自动转换过程中,“是无符号自动转为有符号,还是有符号自动转为无符号”

论坛徽章:
8
CU大牛徽章
日期:2013-04-17 10:59:39CU大牛徽章
日期:2013-04-17 11:01:45CU大牛徽章
日期:2013-04-17 11:02:15CU大牛徽章
日期:2013-04-17 11:02:36CU大牛徽章
日期:2013-04-17 11:02:58技术图书徽章
日期:2013-12-04 10:48:50酉鸡
日期:2014-01-03 10:32:30辰龙
日期:2014-03-06 15:04:07
10 [报告]
发表于 2009-02-26 15:02 |只看该作者
总而言之一句话: 包括typedef搞出来的别名,不同名字的类型就是不同的类型;而一旦涉及不同类型的混合运算,都必须慎之又慎,否则就很容易出麻烦。

比如,short和int都是signed类型,但对于for(short i =0; i < j; i++),j如果是int就可能出现死循环;至于for(int i =0; i < j; i++),当j为unsigned int时出现死循环,就更是司空见惯之事了。


再比如,现在不少库/平台已经将strlen之类的返回值定义为size_t,那么你最好也在代码里把任何可能与之运算/比较/赋值的变量都声明为size_t,否则同样的代码可能换个平台就出了bug。


这不是strlen返回值有无符号的问题,而是类型能否精确匹配的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP