在下面的字符串s中的代码长度为3,长度为t为5.因此,3-5 = -2小于0.那么,为什么下面的代码打印3?
#include <stdio.h>
#include <string.h>
void printlength(char *s, char *t){
unsigned int i=0;
int len = ((strlen(s) - strlen(t))> i ? strlen(s):strlen(t));
printf("%d",len);
}
int main()
{
char *x ="abc";
char *y ="defgh";
printlength(x,y);
return 0;
}
答案 0 :(得分:0)
所以,3-5 = -2
对于签名的整数,对于strlen()
返回且未签名的size_t,这是一个相当大的数字。
答案 1 :(得分:0)
当-2
转换为无符号整数时,结果为unsigned int
值(UINT_MAX + 1- 2
或UINT_MAX - 1
),大于i
。 strlen
会返回size_t
unsigned
数据类型。
同样size_t
是我们使用len
打印的printf("%zu",len)
的正确类型。
令人惊讶的是,当您将减法结果与i
进行比较时,i
的值为0
。你可以这样做
size_t slen = strlen(s);
size_t tlen = strlen(t);
printf("%zu\n", (slen > tlen)? slen : tlen);
答案 2 :(得分:0)
你的问题是从较小的无符号值中减去更大的无符号值。
`(unsigned) 3 - (unsigned) 5` = (unsigned) 4294967294 which is > 0.
使用适当的类型进行计算和正确的逻辑。请注意,strlen
会返回size_t
类型的值。
无需对同一个字符串重复strlen
操作。
您程序的改进版本可能如下所示:
#include <stdio.h>
#include <string.h>
void printlength(char *s, char *t){
size_t len;
size_t sLen = strlen(s);
size_t tLen = strlen(t);
if(sLen > tLen)
len = sLen - tLen;
else
len = tLen - sLen;
printf("len = %u\n\n",len);
printf("NOTE: (unsigned) 3 - (unsigned) 5 = %u", -2);
}
int main()
{
char *x ="abc";
char *y ="defgh";
printlength(x,y);
return 0;
}
输出:
len = 2
NOTE: (unsigned) 3 - (unsigned) 5 = 4294967294
答案 3 :(得分:0)
strlen()
的原型是:
size_t strlen ( const char * );
它的返回值类型是size_t
,在大多数情况下,它是无符号整数类型(通常为unsigned int
或unsigned long
。
当你在两个无符号整数之间进行减法时,如果结果低于0,那么underflow and wrap around将是最小的无符号整数。因此,在典型的32位系统3U - 5U == 4294967294U
和典型的64位系统3UL - 5UL == 18446744073709551614UL
上。 (strlen(s) - strlen(t)) > i
的{{1}}测试与strlen(s) == strlen(t)
的行为完全相同,因为它们的长度相同是唯一可能导致测试失误的情况。
建议在比较整数时避免使用减法。如果你真的想这样做,那就更好了:
i == 0
这样就不太可能有无符号整数溢出。
顺便说一下,如果在变量中保存字符串的长度,则可以减少对strlen(s) > strlen(t) + i
的额外调用。由于您不修改函数中的字符串,因此最好将函数参数声明为strlen()
。还建议你这样做
const char*
因为无法修改字符串文字。任何修改字符串文字的尝试都会调用未定义的行为。