繁体   English   中英

将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章中的主要示例有一些疑问。代码可以总结如下,并且正在使用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; by int pad = 1; ,g ++编译器将返回一个警告:

warning: comparison between signed and unsigned integer expressions [-Werror=sign-compare]
    if (c == 1 + pad)

如果我替换const int pad = 1; by unsigned int pad = 1; ,g ++编译器不会返回警告。

我理解为什么g ++会返回警告,但我不确定以下三点:

  • 使用unsigned int以便与std::string::size_type进行比较是否安全? 在这种情况下,编译器不会返回警告,但我不确定它是否安全。
  • 为什么编译器没有使用原始代码const int pad = 1发出警告。 编译器是否自动将变量pad转换为unsigned int
  • 我也可以替换const int pad = 1; by string::size_type pad = 1; ,但在我看来,变量pad的含义并没有真正与字符串大小相关联。 在这种情况下,这是否是避免在比较中使用不同类型的最佳方法?

从编译器的角度来看:

  1. 比较有符号和无符号变量(非常量)是不安全的
  2. 比较两个不同大小的不带变量是安全的
  3. 如果编译器可以检查该常量是否在有符号变量类型的允许范围内,那么将无符号变量与烧结常数进行比较是安全的 (例如,对于16位有符号整数,在范围内使用常量是安全的[ 0..32767])。

所以你的问题的答案:

  1. 是的,比较unsigned intstd::string::size_type是安全的。
  2. 没有警告,因为编译器可以执行安全检查(编译时:))。
  3. 在比较中使用不同的无符号类型没有问题。 使用unsinged int

如果你使用std::string和默认的分配器(很可能),那么size_type实际上是size_t

[support.types] / 6定义了size_t

实现定义的无符号整数类型,其大小足以包含任何对象的字节大小。

因此,从技术上讲,它不是unsigned int ,但我相信它在大多数情况下都是以这种方式定义的。

现在关于你的第二个问题:如果你使用const int something = 2 ,编译器会看到这个整数是a)永远不会消极而b)永远不会改变,所以将这个变量与size_t进行比较总是安全的。 在某些情况下,编译器可以完全优化变量,并简单地将其全部替换为2

我会说最好在任何地方使用size_type ,因为它更加冗长。

比较有符号值和无符号值是“危险的”,因为当有符号值为负时,您可能无法得到预期的值(它可能表现为非常大的无符号值,因此当a = -1a = -1 a > b给出为trueb = 100 (使用const int有效的,因为编译器知道值没有改变,因此可以说“好吧,这个值总是1,所以这里工作正常”)

只要您要比较的值适合unsigned int (在典型的机器上,略多于40亿)就可以了。

编译器警告的是无符号和有符号整数类型的比较。 这是因为有符号整数可以是负数,其含义是反直觉的。 这是因为签名在比较之前转换为无符号,这意味着负数将比正数更大

使用unsigned int以便与std :: string :: size_type进行比较是否安全? 在这种情况下,编译器不会返回警告,但我不确定它是否安全。

是的,它们都是无符号的,然后语义就是预期的。 如果它们的范围不同,则较窄的转换为更宽的类型。

为什么编译器没有给出原始代码const int pad = 1的警告。编译器是否自动将变量pad转换为unsigned int?

这是因为编译器的构造方式。 编译器解析并在某种程度上优化代码,然后发出警告。 重要的一点是,此时警告被认为是编译器发现有符号整数为1 ,然后可以安全地与无符号整数进行比较。

我也可以替换const int pad = 1; by string :: size_type pad = 1;,但在我看来,变量pad的含义并没有真正链接到字符串大小。 在这种情况下,这是否是避免在比较中使用不同类型的最佳方法?

如果你不希望它是常量,那么最好的解决方案可能是使它至少成为无符号整数类型。 但是,您应该知道普通整数类型和大小之间没有保证关系,例如unsigned int可能更窄,更宽或等于size_tsize_type (后者也可能不同)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM