看看下面的关于strcmp()函数的实现的问题

sun68807 2009-03-31 04:45:32
2个问题:
第1个问题:
各位请看一下以下程序代码段:

int __cdecl strcmp (
const char * src,
const char * dst
)
{
int ret = 0 ;

while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)/*1*/
++src, ++dst;

if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;

return( ret );
}


打上注释1的那一行中,为什么要写“*(unsigned char *)src ”写成*src-*dst不好么?

第2个问题:
另外大家再看下如下的代码实现:

int StringCmp(const char *str1,const char *str2)
{
while ((*str1) && (*str1++ == *str2++))
{
NULL;
}

if (('\0' == *str1) && ('\0' == *str2))
{
return 0;
}
else if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}


这个实现和前面的相比那个好呢?请说下原因
...全文
330 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
sun68807 2009-04-02
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 haozi168 的回复:]
1.考虑到0-255字符的问题吧 因为之前定义的是const char * src, const char * dst -127-127,直接定义const unsigned char * src, const unsigned char * dst 则会在传入时影响到整个函数内都把传入的字符当作无符号,这里只要在比较时得出大小就行了,故只在比较时才转换。

2.也是可以的,无非是一个程序代码最优化的问题,但是两者基本无区别,觉察不到的。值得注意的是while中如果存在||这样的操作时最好不要在其判断内做…
[/Quote]

你说的挺对的,这里的实现应该就是考虑到0-255的问题。所以还是第一个实现更好,更稳定。
sun68807 2009-04-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 xhy_851221 的回复:]
第二个代码有错误
LZ测试
int main()
{
char *a="abc";
char *b="abd";
int c=StringCmp(a,b);
printf("%d\n",c);
return 0;
}
输出0
原因(个人认为):while ((*str1) && (*str1++ == *str2++))
在跳出循环时双双增加到最后一个\0
[/Quote]

你说得对,这个函数是错误的,while ((*str1) && (*str1++ == *str2++)) 语句不能比较最后一个字符,应该把++放到{}内
sun68807 2009-04-02
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 CrazyJeff_Liu 的回复:]
写成 *(unsigned char *)src 或者 *(unsigned char *)dst
可以巧妙地避开了NULL指针问题,
而下面那段代码,不管当str1还是str2为NULL时,都会产生问题,甚至str2为NULL会导致程序崩溃
[/Quote]


我觉得你说的不对,你可以写一个函数试一下strcmp(NULL,NULL),这个语句是会导致程序崩溃的。
ouzhf 2009-03-31
  • 打赏
  • 举报
回复

//strcmp函数:根据str1按照字典顺序小于、等于或大于str2的结果分别返回负整数、0和正整数
int strcmp(const char *str1, const char *str2)
{
for ( ; *str1 == *str2; str1++, str2++)
if (*str1 == '\0')
return 0;
return *str1 - *str2;
}
wohow 2009-03-31
  • 打赏
  • 举报
回复
打上注释1的那一行中,为什么要写“*(unsigned char *)src ”写成*src-*dst不好么?
如果*src值为(char)1,*dst值为(char)255,那么
ret = *(unsigned char *)src - *(unsigned char *)dst的值为-254,而
ret = *src-*dst的值为2(char先转换为int,再做减法运算。转换时是符号扩展的),显然导致判断正负的错误
Rain208 2009-03-31
  • 打赏
  • 举报
回复
第一个好
Rain208 2009-03-31
  • 打赏
  • 举报
回复
打上注释1的那一行中,为什么要写“*(unsigned char *)src ”写成*src-*dst不好么?
无符号数才能比较大小
zyc_glboy 2009-03-31
  • 打赏
  • 举报
回复
把第二个函数改成
int StringCmp(const char *str1,const char *str2)
{
while ((*str1) && (*str1 == *str2))
{
str1++;
str2++;
}

if (*str1 > *str2)
{
return 1;
}
else if (*str1 < *str2)
{
return -1;
}
else
{
return 0;
}
}

至于哪个比较好就说不上来了
liliangbao 2009-03-31
  • 打赏
  • 举报
回复
第二个函数应该修改如下:
int StringCmp(const char *str1,const char *str2)
{
while ((*str1) && (*str1 == *str2))
{
str1++;
str2++

}

if (('\0' == *str1) && ('\0' == *str2))
{
return 0;
}
else if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}

第一个函数那样做:不明白好处,请说明!
BTW:不能避免为NULL吧!

lgccaa 2009-03-31
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 xhy_851221 的回复:]
第二个代码有错误
LZ测试
int main()
{
char *a="abc";
char *b="abd";
int c=StringCmp(a,b);
printf("%d\n",c);
return 0;
}
输出0
原因(个人认为):while ((*str1) && (*str1++ == *str2++))
在跳出循环时双双增加到最后一个\0
[/Quote]
连功能都有问题,就不用考虑那个好那个不好了,功能是最基本的要求
magipan 2009-03-31
  • 打赏
  • 举报
回复
mark,学习
chenzhp 2009-03-31
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 CrazyJeff_Liu 的回复:]
写成 *(unsigned char *)src 或者 *(unsigned char *)dst
可以巧妙地避开了NULL指针问题,
而下面那段代码,不管当str1还是str2为NULL时,都会产生问题,甚至str2为NULL会导致程序崩溃
[/Quote].
CrazyJeff_Liu 2009-03-31
  • 打赏
  • 举报
回复
写成 *(unsigned char *)src 或者 *(unsigned char *)dst
可以巧妙地避开了NULL指针问题,
而下面那段代码,不管当str1还是str2为NULL时,都会产生问题,甚至str2为NULL会导致程序崩溃
duoduo168 2009-03-31
  • 打赏
  • 举报
回复
1.考虑到0-255字符的问题吧 因为之前定义的是const char * src, const char * dst -127-127,直接定义const unsigned char * src, const unsigned char * dst 则会在传入时影响到整个函数内都把传入的字符当作无符号,这里只要在比较时得出大小就行了,故只在比较时才转换。

2.也是可以的,无非是一个程序代码最优化的问题,但是两者基本无区别,觉察不到的。值得注意的是while中如果存在||这样的操作时最好不要在其判断内做++ --操作,防止编译器优化而不执行,现在这里是&&没有问题,提个醒。
xhy_851221 2009-03-31
  • 打赏
  • 举报
回复
第一个不知道为什么
等待答案
xhy_851221 2009-03-31
  • 打赏
  • 举报
回复
第二个代码有错误
LZ测试
int main()
{
char *a="abc";
char *b="abd";
int c=StringCmp(a,b);
printf("%d\n",c);
return 0;
}
输出0
原因(个人认为):while ((*str1) && (*str1++ == *str2++))
在跳出循环时双双增加到最后一个\0

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧