为什么以下代码将O / P作为3而不是5?

时间:2018-01-14 03:56:29

标签: c

在下面的字符串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;
}

4 个答案:

答案 0 :(得分:0)

  

所以,3-5 = -2

对于签名的整数,对于strlen()返回且未签名的size_t,这是一个相当大的数字。

答案 1 :(得分:0)

-2转换为无符号整数时,结果为unsigned int值(UINT_MAX + 1- 2UINT_MAX - 1),大于istrlen会返回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 intunsigned 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*

因为无法修改字符串文字。任何修改字符串文字的尝试都会调用未定义的行为。