【问题标题】:Converting a size_t into an integer (c++)将 size_t 转换为整数 (c++)
【发布时间】:2011-01-13 22:44:36
【问题描述】:

我一直在尝试创建一个 for 循环,该循环将根据网络数据包的长度进行迭代。在 API 中,通过 event.packet->dataLength 存在一个变量 (size_t)。我想从 0 迭代到 event.packet->dataLength - 7 每次迭代时 i 增加 10,但我遇到了麻烦。

我寻找解决方案,但找不到任何有用的东西。我尝试将 size_t 转换为 unsigned int 并用它进行算术运算,但不幸的是它不起作用。基本上我想要的就是这个:

for (int i = 0; i < event.packet->dataLength - 7; i+=10) { }

虽然每次我做这样的事情或尝试转换时, i

【问题讨论】:

  • 想一想:static_cast&lt;unsigned int&gt;(-1)的值是多少?当event.packet-&gt;dataLength 小于 7 时会发生什么?
  • 为什么i 也不能成为size_t?此外,除非长度始终等于 7 mod 10,否则这是一个非常特殊的循环尝试。
  • 您是否尝试将event.packet-&gt;dataLength 转换为int
  • 虽然我们可以修复类型不一致,但我们无法修复您的逻辑,直到您 tell us the goal and your code
  • @genpfault 哇,我什至没有想到,目前它不起作用,但很可能是因为它小于 7。我讨厌我做愚蠢的事情。

标签: c++ integer size-t


【解决方案1】:

你为什么不改变i的类型?

for (size_t i = 0; i < event.packet->dataLength - 7; i+=10) { }

尽量保持所有一起使用的变量的类型相同;应该避免强制转换。

C++03 中没有size_t 的格式说明符,您必须转换为最大的无符号整数类型并打印出来。 (C++0x 中size_t 的格式说明符是%zu)。但是,无论如何你都不应该使用printf

std::cout << i; // print i, even if it's a size_t

虽然流可能更冗长,但它们的类型更安全,并且不需要您记住任何内容。

请记住,您的实际循环逻辑可能存在缺陷。 (正如 genpfault 所指出的,当dataLength - 7 为负数时会发生什么?)

【讨论】:

  • 如果dataLength - 7 为负数,这将无济于事,而且我认为它不会有任何好处。
  • @David:不会,这就是我提到它的原因。在不知道意图的情况下很难说修复是什么。
  • @Jean:什么是“没用”?你能告诉我们你的真实代码吗?您要解决的实际问题是什么?
  • while (i + 7 &lt; event.packet-&gt;dataLength) 怎么样?
  • -1 @Gman:你的解决方案行不通。 OP表示,“每次”减法都会导致“巨大的数字”。意味着典型的数据包大小小于 7,正如您在最后指出的那样,这是不好的。
【解决方案2】:

用有符号算术做所有事情。试试:

for (int i = 0; i < int(event.packet->dataLength) - 7; i+=10) { }

一旦你开始使用可能为负数的无符号算术,并使用像&lt; 这样的比较运算符,你就有麻烦了。更容易签署。

【讨论】:

  • 嗯,我不得不删除我原来的评论,在标准保证的行为方面考虑得太多了。在二进制补码机器上,使用非反常编译器,即在实践中,以上将起作用。但是,将可能巨大的无符号值转换为int 是正式的 UB。所以,最好修正括号。干杯,
  • @Alf P. Steinbach:谢谢 - 即使在您发表评论之后,我还是花了一点时间才意识到您的意思,所以这不仅仅是一个错字。
【解决方案3】:

dataLength >= 7 吗?如果dataLength-7的结果是负数,如果你把它解释为无符号,结果是一个很大的整数。

【讨论】:

    【解决方案4】:

    对 i 使用 size_t。

    对于 printf,如果没有 C99,只有 C90,强制转换为 unsigned long 或 unsigned long long。例如:

    for (size_t i = 0; i < 10; ++i)
            //printf("%llu\n", (unsigned long long)i);
            printf("%lu\n", (unsigned long)i);
    

    否则使用 %zu

    【讨论】:

      【解决方案5】:

      你应该首先检查event.packet-&gt;dataLength &lt; 7。现在,如果它小于 7,您将得到小于 0 的值用作无符号:例如0 = 0x00000000; -1 = 0 - 1 = 0xFFFFFFFF。

      再次检查:

      if (event.packet->dataLength < 7) {
        ...
      } else {
        for (size_t i = 0; i < event.packet->dataLength - 7; i+=10) { }
      }
      

      【讨论】:

        【解决方案6】:

        “每次我做这样的事情或尝试我的转换时,我

        这表示原始数据包长度小于 7(你减去 7)。

        一种解决方法是使用实​​际中足够大的有符号整数类型,标准库为此提供了ptrdiff_t。喜欢,

        #include <stdlib.h>   // Not sure, but I think it was this one.
        
        typedef ptrdiff_t    Size;
        typedef Size         Index;
        
        void foo()
        {
            // ...
            for( Index i = 0; i < Size( event.packet->dataLength ) - 7; i += 10 )
            {
                // ...
            }
        }
        

        一个更麻烦的解决方法是将整个内容嵌入到一个if 中,以检查大小是否至少为 7。

        干杯,

        【讨论】:

          【解决方案7】:

          由于event.packet-&gt;dataLength 返回一个无符号类型size_t

          1) 使用size_t 作为索引变量类型。

          2) 确保数学不会下溢。 @beldaz。不是从event.packet-&gt;dataLength 中减去 7,而是将 7 加到 i 中。

          // for (int i = 0; i < event.packet->dataLength - 7; i+=10) { }
          for (size_t i = 0; i + 7 < event.packet->dataLength; i += 10) { }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-05-01
            • 1970-01-01
            • 1970-01-01
            • 2011-12-10
            • 1970-01-01
            • 2016-03-06
            • 2014-01-08
            相关资源
            最近更新 更多