为什么 c++ string1.size() 减去 string2.size() 得到错误的答案
Why c++ string1.size() minus string2.size() got wrong answer?
#include <string>
#include <iostream>
using namespace std;
int main()
{
string haystack = "aaa";
string needle = "aaaa";
int i = 0;
if(i <= haystack.size() - needle.size())
cout<<"why 0<-1?"<<endl;
return 0;
}
输出:为什么是0<-1?按任意键继续...
为什么我们得到这个输出?我认为不应该执行"if"语句,因为 0 大于 3-4=-1。谢谢!
std::string::size
的返回类型是 std::size_t
。
这是一个无符号类型。因此,由于您的减法导致负值,它将基于二的补码进行环绕,导致非常大的数字远远大于0
。
由于历史原因,标准库通常使用 size_t
(无符号类型)作为大小函数的结果类型。一个例外是 std::count
.但std::string::size()
是size_t
功能之一,
由于该语言保证了无符号类型表达式的模块化算术,因此您可以获得环绕,其中-1
成为无符号类型的最大值。
另一个和IMO更明显的愚蠢后果是
std::string( "Hello" ).size() < -1
是有保证的。只是纯粹的废话作为源代码文本,当人们回想起高级源代码的目的是更清楚地与人类沟通时。
为了避免这种混乱,你可以定义一个逻辑有符号Size
类型作为ptrdiff_t
的别名(这是size_t
的有符号类型对应物)和大小相同的函数static_size
、n_items
和length
,加上一个检查器is_empty
,如下所示:
#pragma once
// p/cppx/core_language_support/sizes_and_lengths.hpp
// Copyright © Alf P. Steinbach 2015. Boost Software License 1.0.
#include <p/cppx/core_language_support/basic_types.hpp>
#include <p/cppx/core_language_support/overloading.hpp> // cppx::(Object_argument etc.)
#include <p/cppx/core_language_support/type_builders.hpp> // cppx::(Ptr_, Ref_, Array_of_, ...)
#include <p/cppx/core_language_support/tmp/If_.hpp> // cppx::(If_, Is_)
#include <p/cppx/core_language_support/tmp/type_relationships.hpp> // cppx::Is_convertible_to_
#include <string> // std::basic_string
#include <utility> // std::declval
namespace progrock{ namespace cppx{
// These templates use size_t to accommodate g++, which has bug in this area.
// static_size()
// Static capacity of a collection.
template< class Type, size_t n >
constexpr
auto static_size( In_ref_<Raw_array_of_<n, Type>> )
-> Size
{ return n; }
template< class Type, size_t n >
constexpr
auto static_size( In_ref_<Array_of_<n, Type>> )
-> Size
{ return n; }
template< size_t n >
constexpr
auto static_size( In_ref_<std::bitset<n>> )
-> Size
{ return n; }
// n_items() & is_empty()
// Right-typed (signed integer) dynamic size of a collection.
template< class Type >
auto n_items( In_ref_<Type> o )
-> Size
{ return o.size(); }
template< size_t n >
auto n_items( In_ref_<std::bitset<n>> o )
-> Size
{ return o.count(); } // Corresponds to std::set<int>::size()
namespace impl {
using std::declval;
template< class Type >
constexpr
auto has_std_empty_checker( ... )
-> bool
{ return false; }
template< class Type >
constexpr
auto has_std_empty_checker( int )
-> If_<
Is_<bool, decltype( declval<const Type>().empty() )>, // CFINAE
Then_<bool> // SFINAE
>
{ return true; }
struct Using_empty_method
{
template< class Type >
auto is_empty( In_ref_<Type> o ) const
-> bool
{ return o.empty(); }
};
struct Using_n_items_function
{
template< class Type >
auto is_empty( In_ref_<Type> o ) const
-> bool
{ return (n_items( o ) == 0); }
};
} // namespace impl
template< class Type >
constexpr
auto has_std_empty_checker()
-> bool
{ return impl::has_std_empty_checker<Type>( 42 ); }
template< class Type >
auto is_empty( In_ref_<Type> o )
-> bool
{
using Impl = Ifc_<
has_std_empty_checker<Type>(),
Then_<impl::Using_empty_method>,
Else_<impl::Using_n_items_function>
>;
return Impl().is_empty( o );
}
template< size_t n >
auto is_empty( In_ref_<std::bitset<n>> bits )
-> bool
{ return bits.none(); }
// length() & length_of_literal() & is_empty
// Lengths of strings.
template< class Char, size_t n >
constexpr
auto length_of_literal( In_ref_<Raw_array_of_<n, Char>> ) // "length" wraps this.
-> Size
{ return n - 1; }
template< class Type >
auto length( Object_argument, In_ref_<Type> s )
-> Size
{ return s.length(); }
template< class Char
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto length( Pointer_argument, In_value_<Ptr_<const Char>> s )
-> Size
{
auto p = s;
while( *p != 0 ) { ++p; }
return p - s;
}
template< class Char, size_t n
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto constexpr length( Array_argument, In_ref_<Raw_array_of_<n, Char>> a )
-> Size
{ return length_of_literal( a ); }
template< class Type >
auto length( In_ref_<Type> o )
-> Size
{ return length( Arg_kind_<Type>(), o ); }
template< class Char
, class Enabled_ = If_< Is_in_< Character_types, Char > >
>
auto is_empty( In_value_<Ptr_<const Char>> s )
-> bool
{ return (*s == 0); }
}} // namespace progrock::cppx
如果你想直接部分或全部使用此代码,而不从cppx库中引入支持文件,你必须翻译例如 In_
到您喜欢的逻辑参数类型,依此类推。cppx 库只是一件非常正在进行的事情,但它已经可以按原样使用。它提供了诸如上述内容的内容,这些基础知识以某种方式错过了成为标准库的一部分,甚至没有被提议。
相关文章:
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 在函数中使用 const int size 参数创建数组会在 Visual Studio 中抛出错误 C++:表达式的计
- 错误:'class std::unique_ptr<std::set<long unsigned int> >'没有名为 'size' 的成员
- 为什么会出现错误:size不是std的成员
- 调用 list.size() 方法给出错误"expression must have class type"
- 声明数组时出现 SIGSEGV 错误,而不创建新的 int[size]
- 了解 glibc 错误"corrupted size vs. prev_size"
- 如何在使用CreateRemoteThread API时修复"LPVOID: unknown size"错误?
- vtkTypeTraits.h 错误:"Type long is not 4 or 8 bytes in size."
- 在C++中定义包含TTF_Font变量的向量时"Undefined size"错误
- 二叉搜索树瓦尔格林德错误"Invalid read of size 8"
- 为什么 size() 在与其他堆栈交换元素后提供错误的堆栈大小?
- 错误:addressAnitizer:否定尺寸 - 帕拉姆:( size = -4)
- 如何修复'Size of list( a class) is unknown or zero error'和"声明语法错误"?
- 错误:"SIZE"在使用模板<类 T、int MAX_SIZE >时无法出现在常量表达式中
- 无法在 Mac OS X 上分配内存错误 - java(xx,xx) malloc: *** mmap(size=XX)
- 为什么 vector.size() 函数给我一个错误
- 调用 size() 的常量映射<字符串,矢量<int>>导致错误
- 为什么瓦尔格林德会给出"Invalid read of size 1"错误?
- c++中的快速排序array.size()错误