为啥这个 stl 函数调用会导致不正确的布尔评估? [复制]

Posted

技术标签:

【中文标题】为啥这个 stl 函数调用会导致不正确的布尔评估? [复制]【英文标题】:Why does this stl function call result in an incorrect boolean evaluation? [duplicate]为什么这个 stl 函数调用会导致不正确的布尔评估? [复制] 【发布时间】:2018-12-30 23:28:14 【问题描述】:

当我遇到一个涉及检查向量大小的奇怪情况时,我正在谦虚地编码。下面列出了该问题的一个独立版本:

#include <iostream>
#include <string>
#include <vector>

int main() 

  std::vector<std::string> cw = "org","app","tag";

  int j = -1;

  int len = cw.size();

  bool a = j>=cw.size();
  bool b = j>=len;


  std::cout<<"cw.size(): "<<cw.size()<<std::endl;
  std::cout<<"len: "<<len<<std::endl;

  std::cout<<a<<std::endl;
  std::cout<<b<<std::endl;

  return 0;

同时使用 g++ 和 clang++(使用 -std=c++11 标志)编译并运行会产生以下输出:

cw.size(): 3
len: 3
1
0

为什么j &gt;= cw.size() 评估为真?稍微试验一下 j 的任何负值都会导致这种奇怪的差异。

【问题讨论】:

阅读integral conversions。请注意,cw.zize() 返回一个无符号类型。 cw.size() 未签名。在比较中,j 的负值被强制转换为一个非常大的正值。 启用附加警告(-Wall -Wextra 用于 gcc/clang),编译器可能会警告您此类内容。 这些 cmets 应该是答案 啊,绝对应该按照@user10605163 的建议发出警告,指出我的问题所在。 【参考方案1】:

这里的缺陷是有符号整数转换,当您将有符号整数值与无符号整数值进行比较时会出现这种转换。在这种情况下,有符号值将被转换为无符号值,如果值为负数,则会得到UINT_MAX - val + 1。所以-1在比较之前会被转换成一个很大的数字。

但是,当您将无符号值分配给有符号值时,例如int len = vec.size(),那么无符号值将变为有符号值,例如,(unsigned)10 将得到 (signed)10。并且两个有符号整数之间的比较不会转换两个操作数中的任何一个,并且会按预期工作。

你可以很容易地模拟这个:

int main() 
    int j = -1;

    bool a = j >= (unsigned int)10; // signed >= unsigned; will convert j to unsigned int, yielding 4294967295
    bool b = j >= (signed int)10; // signed >= signed; will not convert j

    cout << a << endl << b << endl;

    unsigned int j_unsigned = j;
    cout << "unsigned_j: " << j_unsigned << endl;

输出:

1
0
unsigned_j: 4294967295

【讨论】:

以上是关于为啥这个 stl 函数调用会导致不正确的布尔评估? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

重读STL源码剖析:析构

页面项目的布尔评估不正确

为啥这个带有布尔变量的函数不起作用?

为啥 C# 'is' 运算符在比较两个布尔值时会给出正确的结果,我应该使用它吗?

为啥在 bash if 语句中未设置的变量被评估为 0

Torch JIT Trace = TracerWarning:将张量转换为 Python 布尔值可能会导致跟踪不正确