#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? 按任意键继续......
为什么我们得到这个输出?我想&#34;如果&#34;不应该执行语句因为0大于3-4 = -1。 谢谢!
答案 0 :(得分:10)
std::string::size
的返回类型为std::size_t
。
这是 unsigned 类型。因此,由于您的减法会产生一个负值,it will wrap around基于two's complement,因此会产生远大于0
的非常大的数字。
答案 1 :(得分:2)
由于历史原因,标准库通常使用size_t
( unsigned 类型)作为size函数的结果类型。 std::count
是一个例外。但是std::string::size()
是size_t
函数中的一部分,
由于该语言保证了无符号类型表达式的模运算,因此在-1
成为无符号类型的最大值时会得到回绕。
另一个和IMO更明显的愚蠢后果是
std::string( "Hello" ).size() < -1
保证。只是纯粹的废话作为源代码文本,当人们回忆起高级源代码的目的是为了更清楚地与人沟通。
为了避免这种混乱,您可以将逻辑签名的Size
类型定义为ptrdiff_t
的别名(与size_t
对应的签名类型)和同上大小的函数{{1} },static_size
和n_items
以及检查器length
,如下所示:
is_empty
如果您想部分或全部使用此代码,而不直接从cppx library引入支持文件,则必须翻译,例如#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库只是一个非常重要的事情,但它已经可以使用了。它提供了如上所述的东西,不知何故错过了成为标准库的一部分,甚至被提议的基础知识。