|
有符号的大整数加减法,最终都会进行无符号的加减法。
而无符号的减法,必须得是较大者作为被减数,也就是说得先有个比较运算。
而就是这一步,曾害得我花了好几个小时去排查一个 bug,最终居然是微软编译器的问题!- // test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include "pch.h"#include <compare>#include <iostream>// 2020-03-16, gxqcn 发现编译器 bug: 如写成 const auto cmp{ *--pl <=> *--pr }, 当 0 != cmp 时,指针会多移动一次!int main(){ const auto test{ []( auto a, auto b ) { std::cout << "before compare: a=" << a << " b=" << b << "\n"; const auto cmp{ a++ <=> b++ }; std::cout << "after compare: a=" << a << " b=" << b << "\n\n"; // 为了对比检测 std::max() 是否有类似表现, std::cout << "std::max( a++, b++ ) = " << std::max( a++, b++ ) << "\n"; std::cout << "after std::max: a=" << a << " b=" << b << "\n\n"; }}; test( 1, 1 ); // 测试表明:当相等时,表现与预期相符 test( 1, 2 ); // 测试表明:当不等时,表现与预期不符 std::cout << "-------------------------\n\n"; int v1[]{ 1, 2, 3, 4, 5, 6 }; int v2[]{ 1, 2, 0, 9, 0, 6 }; auto p1{ std::cbegin( v1 ) - 1 }; auto p2{ std::cbegin( v2 ) - 1 }; std::cout << "compare: v1{ 1, 2, 3, 4, 5, 6 } <=> v2{ 1, 2, 0, 9, 0, 6 }\n\n"; for ( auto index{ 0 }; sizeof( v1 ) / sizeof( v1[ 0 ] ) != index; ++index ) { if ( const auto cmp{ *++p1 <=> *++p2 }; 0 != cmp ) { std::cout << "v1[" << index << "] = " << v1[ index ] << "; *p1 =" << *p1 << "\n"; std::cout << "v2[" << index << "] = " << v2[ index ] << "; *p2 =" << *p2 << "\n"; if ( 0 < cmp ) { std::cout << "\nv1 > v2"; } else { std::cout << "\nv1 < v2"; } if (( v1[ index ] <=> v2[ index ] ) == cmp ) { std::cout << ", it's right.\n\n"; } else { std::cout << " ?! it's wrong!!\n\n"; } break; } } system( "pause" );}
复制代码 注意:需在 属性页->常规->C++语言标准 中设定“预览 - 最新 C++ 工作草案中的功能 (std:c++latest)”才能编译
其运行结果如下:- before compare: a=1 b=1after compare: a=2 b=2std::max( a++, b++ ) = 2after std::max: a=3 b=3before compare: a=1 b=2after compare: a=3 b=4std::max( a++, b++ ) = 4after std::max: a=4 b=5-------------------------compare: v1{ 1, 2, 3, 4, 5, 6 } <=> v2{ 1, 2, 0, 9, 0, 6 }v1[2] = 3; *p1 =4v2[2] = 0; *p2 =9v1 < v2 ?! it's wrong!!请按任意键继续. . .
复制代码 这个 bug 不仅是运算结果不对的问题,还有导致指针越界的风险,
解决的方式是:在 <=> 两端,尽量避免自增/自减等运算,
不过这只是避坑而已,坑仍在那里!
这个 bug 是昨天上午发现的,当时版本是 VS2019 16.4.6;
今早微软对它进行了更新,版本为 16.5.0;
但刚才测试了下,该 bug 依然存在。 |
|