if 语句选择了错误的条件

if statement selects the wrong condition

我对这段代码有疑问:我不知道为什么它打印 B 而不是 A,因为条件为真。 strlen(x)明显大于i。你能帮帮我吗?

#include <stdio.h>
#include <string.h>

int main()
{
   char x[]="Hello";
   int i = -3;
   
   if(strlen(x)>i)
   {
       printf("A");
   }
   else
   {
       printf("B");
   }
    return 0;
}

您正在尝试比较有符号整数和无符号整数。 尝试 if(signed(strlen(x))>i){} 或者您可以将 I 的值更改为正整数。

标准函数strlen声明为

size_t strlen(const char *s);

其中类型 size_t 是一个实现定义的无符号整数类型,其等级不低于类型 int 的等级。通常类型 size_t 被定义为类型 unsigned long.

的别名

在用作 if 语句条件的表达式中

if(strlen(x)>i)

编译器使用通常的算术转换来确定操作数的常见类型。即通过传播符号位将操作数 i 转换为类型 size_t。结果,转换后的操作数的值是一个非常大的 size_t 类型的无符号整数,它大于调用 strlen 的返回值。因此条件计算结果为逻辑错误。

这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    int i = -3;
    
    printf( "( size_t )i = %zu\n", ( size_t )i );
    
    return 0;
}

它的输出可能看起来像

( size_t )i = 18446744073709551613

如果你想在你的程序中得到预期的结果你应该写

if( ( int )strlen(x)>i)

或者例如

if( ( long int )strlen(x)>i)

也就是说,你需要将函数 strlen 返回的值转换为某种有符号整数类型。

来自 C17 document,6.3.1.8,页码 39

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type

size_t strlen(const char *s);

这里,strlen(x) return 类型的值 size_t (unsigned long int)。但是 iint 类型。 size_t 的排名高于 int 的排名。因此,i 将被提升为 size_t

-3 的 Unsigend 值是 4294967293(在我的系统中)。和 strlen(x) = 5 ,所以它会打印 else 语句。