将 unsigned int 与 std::string::size_type 进行比较是否安全
Is it safe to compare an unsigned int with a std::string::size_type
我正在阅读 Andrew Koenig 和 Barbara E. Moo 的书"Accelerated C++",我对第 2 章中的主要示例有一些疑问。代码可以总结如下,并且在没有 warning/error 与 g++:
#include <string>
using std::string;
int main()
{
const string greeting = "Hello, world!";
// OK
const int pad = 1;
// KO
// int pad = 1;
// OK
// unsigned int pad = 1;
const string::size_type cols = greeting.size() + 2 + pad * 2;
string::size_type c = 0;
if (c == 1 + pad)
{;}
return 0;
}
但是,如果我将 const int pad = 1;
替换为 int pad = 1;
,g++ 编译器将 return 发出警告:
warning: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
if (c == 1 + pad)
如果我用 unsigned int pad = 1;
替换 const int pad = 1;
,g++ 编译器将不会 return 警告。
我理解为什么 g++ return 警告,但我不确定以下三点:
- 为了与
std::string::size_type
进行比较,使用 unsigned int
是否安全?在这种情况下,编译器不会 return 发出警告,但我不确定它是否安全。
- 为什么编译器没有给出原始代码的警告
const int pad = 1
。编译器是否自动将变量 pad
转换为 unsigned int
?
- 我也可以将
const int pad = 1;
替换为 string::size_type pad = 1;
,但在我看来,变量 pad
的含义并没有真正与字符串大小相关联。不过,在这种情况下,这是否是避免在比较中使用不同类型的最佳方法?
如果您将 std::string
与默认分配器一起使用(这很可能),那么 size_type
实际上是 size_t
.
[support.types]/6 定义 size_t
是
an implementation-defined unsigned integer type that is large enough to contain the size
in bytes of any object.
所以在技术上不能保证它是 unsigned int
,但我相信在大多数情况下它都是这样定义的。
现在关于你的第二个问题:如果你使用 const int something = 2
,编译器会发现这个整数 a) 从不为负且 b) 从不改变,所以将这个变量与 [=12= 进行比较总是安全的].在某些情况下,编译器可能会完全优化变量并简单地用 2
.
替换所有出现的变量
我会说最好在任何地方都使用 size_type
,因为它更冗长。
比较有符号和无符号值是 "dangerous",因为当有符号值为负时,您可能得不到预期的结果(它很可能表现为一个非常大的无符号值,因此 a > b
在 a = -1
和 b = 100
时给出 true
。(const int
的使用是有效的,因为编译器知道值没有改变,因此可以说 "well, this value is always 1, so it works fine here" )
只要您要比较的值在 unsigned int
范围内(在典型的机器上,略高于 40 亿)就可以了。
编译器警告的是无符号和有符号整数类型的比较。这是因为有符号整数可以是负数,意思是违反直觉的。这是因为有符号在比较之前被转换为无符号,这意味着负数会比较大于正数。
Is it safe to use an unsigned int in order to compare with a std::string::size_type? The compiler does not return a warning in that case but I am not sure if it is safe.
是的,它们都是无符号的,语义符合预期。如果它们的范围不同,则将较窄的转换为较宽的类型。
Why is the compiler not giving a warning with the original code const int pad = 1. Is the compiler automatically converting the variable pad to an unsigned int?
这是因为编译器的构造方式。编译器在发出警告之前解析并在某种程度上优化代码。重要的一点是,在考虑此警告时,编译器现在知道有符号整数是 1
,然后可以安全地与无符号整数进行比较。
I could also replace const int pad = 1; by string::size_type pad = 1;, but the meaning of the variable pad is not really linked to a string size in my opinion. Still, would this be the best approach in that case to avoid having different types in the comparison?
如果您不希望它保持不变,最好的解决方案可能是使其至少成为无符号整数类型。但是你应该知道,正常整数类型和大小之间没有保证的关系,例如 unsigned int
可能更窄、更宽或等于 size_t
和 size_type
(后者也可能不同).
从编译器的角度来看:
- 比较有符号和无符号变量(非常量)是不安全。
- 比较 2 个不同大小的未签名变量是安全的。
- 如果编译器可以检查常量是否在有符号变量类型的允许范围内(例如,对于16 位有符号整数,使用 [0..32767] 范围内的常量是安全的。
所以你的问题的答案:
- 是的,比较
unsigned int
和 std::string::size_type
是安全的。
- 没有警告,因为编译器可以执行安全检查(编译时:))。
- 使用不同的 unsigned 类型进行比较,没有 问题。使用
unsinged int
.
我正在阅读 Andrew Koenig 和 Barbara E. Moo 的书"Accelerated C++",我对第 2 章中的主要示例有一些疑问。代码可以总结如下,并且在没有 warning/error 与 g++:
#include <string>
using std::string;
int main()
{
const string greeting = "Hello, world!";
// OK
const int pad = 1;
// KO
// int pad = 1;
// OK
// unsigned int pad = 1;
const string::size_type cols = greeting.size() + 2 + pad * 2;
string::size_type c = 0;
if (c == 1 + pad)
{;}
return 0;
}
但是,如果我将 const int pad = 1;
替换为 int pad = 1;
,g++ 编译器将 return 发出警告:
warning: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
if (c == 1 + pad)
如果我用 unsigned int pad = 1;
替换 const int pad = 1;
,g++ 编译器将不会 return 警告。
我理解为什么 g++ return 警告,但我不确定以下三点:
- 为了与
std::string::size_type
进行比较,使用unsigned int
是否安全?在这种情况下,编译器不会 return 发出警告,但我不确定它是否安全。 - 为什么编译器没有给出原始代码的警告
const int pad = 1
。编译器是否自动将变量pad
转换为unsigned int
? - 我也可以将
const int pad = 1;
替换为string::size_type pad = 1;
,但在我看来,变量pad
的含义并没有真正与字符串大小相关联。不过,在这种情况下,这是否是避免在比较中使用不同类型的最佳方法?
如果您将 std::string
与默认分配器一起使用(这很可能),那么 size_type
实际上是 size_t
.
[support.types]/6 定义 size_t
是
an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object.
所以在技术上不能保证它是 unsigned int
,但我相信在大多数情况下它都是这样定义的。
现在关于你的第二个问题:如果你使用 const int something = 2
,编译器会发现这个整数 a) 从不为负且 b) 从不改变,所以将这个变量与 [=12= 进行比较总是安全的].在某些情况下,编译器可能会完全优化变量并简单地用 2
.
我会说最好在任何地方都使用 size_type
,因为它更冗长。
比较有符号和无符号值是 "dangerous",因为当有符号值为负时,您可能得不到预期的结果(它很可能表现为一个非常大的无符号值,因此 a > b
在 a = -1
和 b = 100
时给出 true
。(const int
的使用是有效的,因为编译器知道值没有改变,因此可以说 "well, this value is always 1, so it works fine here" )
只要您要比较的值在 unsigned int
范围内(在典型的机器上,略高于 40 亿)就可以了。
编译器警告的是无符号和有符号整数类型的比较。这是因为有符号整数可以是负数,意思是违反直觉的。这是因为有符号在比较之前被转换为无符号,这意味着负数会比较大于正数。
Is it safe to use an unsigned int in order to compare with a std::string::size_type? The compiler does not return a warning in that case but I am not sure if it is safe.
是的,它们都是无符号的,语义符合预期。如果它们的范围不同,则将较窄的转换为较宽的类型。
Why is the compiler not giving a warning with the original code const int pad = 1. Is the compiler automatically converting the variable pad to an unsigned int?
这是因为编译器的构造方式。编译器在发出警告之前解析并在某种程度上优化代码。重要的一点是,在考虑此警告时,编译器现在知道有符号整数是 1
,然后可以安全地与无符号整数进行比较。
I could also replace const int pad = 1; by string::size_type pad = 1;, but the meaning of the variable pad is not really linked to a string size in my opinion. Still, would this be the best approach in that case to avoid having different types in the comparison?
如果您不希望它保持不变,最好的解决方案可能是使其至少成为无符号整数类型。但是你应该知道,正常整数类型和大小之间没有保证的关系,例如 unsigned int
可能更窄、更宽或等于 size_t
和 size_type
(后者也可能不同).
从编译器的角度来看:
- 比较有符号和无符号变量(非常量)是不安全。
- 比较 2 个不同大小的未签名变量是安全的。
- 如果编译器可以检查常量是否在有符号变量类型的允许范围内(例如,对于16 位有符号整数,使用 [0..32767] 范围内的常量是安全的。
所以你的问题的答案:
- 是的,比较
unsigned int
和std::string::size_type
是安全的。 - 没有警告,因为编译器可以执行安全检查(编译时:))。
- 使用不同的 unsigned 类型进行比较,没有 问题。使用
unsinged int
.