RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1208559
Accepted
juice
juice
Asked:2021-11-23 17:41:06 +0000 UTC2021-11-23 17:41:06 +0000 UTC 2021-11-23 17:41:06 +0000 UTC

为什么 read() 接受使用有符号类型的多个字节?

  • 772

std::ifstream::read(char_type*, std::streamsize)std::streamsize接受使用有符号类型和std::fread(void*, std::size_t, std::size_t, std::FILE*)- 使用无符号类型读取的字节数std::size_t。同时,在许多示例中,无论是那里还是那里,对于字节数,他们都使用sizeof,结果为std::size_t. 大小std::vector<char>也是无符号的。那么为什么这个函数采用有符号类型呢?如何正确转换类型以毫无问题地填充字节向量?

c++
  • 3 3 个回答
  • 10 Views

3 个回答

  • Voted
  1. Best Answer
    KoVadim
    2021-11-23T19:59:18Z2021-11-23T19:59:18Z

    我认为正确的答案是它发生在历史上。一开始,C/C++ 积极地将 int 用于一切(在旧 C 中,它通常是“默认类型”)。甚至没有人想到某些文件会大于 2 GB(“这些都是巨大的大小”)——现在他们认为大约 64 分之二。此外,使用负数作为错误的标志非常方便. 如果读取了某些内容,则相同的 read/ recv返回正数,如果文件/套接字关闭则返回零,如果发生错误则返回负数。这很方便。

    但随后数学家们看着它说:“好吧,数组的大小怎么可能是负数?” 另外,当我们尝试添加两个数组大小时会导致错误,其中一个是负数(因为它实际上是读取错误的字节数)。并且决定最好存储在无符号类型中,并以另一种方式返回错误(例如,带有异常或返回代码)。但不是每个人都这样,java中没有无符号类型(或者它们已经出现了?)。

    即便如此,许多人还是不想因为错误而放弃惯用的 -1。从好的方面来说,有很多地方使用 0xFFF...FF 来准确地指示错误,这有时会导致很酷的错误(尝试分配如此多的内存通常以没有好处的结果而告终)。

    然后标准化委员会的聪明人又看了一遍,决定,别装了,我们加ssize——和size一样,只是一个标志。有一些有趣的事情可以解释为什么这一切都是必要的。

    • 6
  2. V31R
    2021-11-23T18:09:40Z2021-11-23T18:09:40Z

    该类型std :: streamsize是一个有符号整数类型,用于表示在 I/O 操作中传递的字符数或 I/O 缓冲区的大小。它用作签名对应物std :: size_t,类似于 POSIX 类型ssize_t。

    除了构造函数,从不使用std :: strstreambuf负值。std :: streamsize

    C++ 草案标准在第 27.5.2 节类型中有以下脚注 296,其中说:

    streamsize在 ISO C 将使用的大多数地方使用size_t. streamsize可以在大多数情况下使用size_t,除了strstreambuf需要负值的构造函数。它可能应该是一个有符号类型,对应size_t(这就是 Posix.2 所称的ssize_t)。

    我们看到在D.7.1.1构造函数strstreambuf中我们有以下条目:

    strstreambuf(char* gnext_arg, streamsize n, char *pbeg_arg = 0);
    strstreambuf(signed char* gnext_arg, streamsize n,
       signed char *pbeg_arg = 0);
    strstreambuf(unsigned char* gnext_arg, streamsize n,
       unsigned char *pbeg_arg = 0);
    

    并说:

    gnext_arg必须指向数组对象的第一个元素,其元素数 N 定义如下:

    从下面的讨论中,我们可以看到 n 的类型streamsize确实需要能够取负值:

    • 如果 n > 0,则 N 等于 n。

    • 如果 n == 0,则 N 等于std :: strlen (gnext_arg)。

    • 如果 n <0,N 等于 INT_MAX。

    • 1
  3. wololo
    2021-11-23T21:56:28Z2021-11-23T21:56:28Z

    我不会判断该类型是有符号整数类型是如何发生的std::streamsize,但是,我会注意到,即使它是无符号的,那么您的主要问题 - “正确的类型转换” - 将无法以任何方式解决。

    语言标准不保证

    1. 一个类型的所有值std::size_t都可以用该类型来表示std::streamsize,
    2. 该类型的所有非负值std::streamsize都可以由该类型表示std::size_t,
    3. 向量的大小std::vector<some_type>由类型表示std::streamsize,
    4. 一个类型的任何值std::streamsize都可以用一个类型来表示std::vector<some_type>::difference_type
    5. 该类型的任何值std::size_t都可以由该类型表示std::vector<some_type>::size_type。

    因此,为了完全确保在将一种类型的值转换为另一种类型的值时,不会发生意外截断,您应该在转换之前检查转换后的值是否适合目标类型。

    例如明确地:

    if ( char_vect.size() <= static_cast<std::uintmax_t>(std::numeric_limits<std::streamsize>::max()) )
        fout.write(&char_vect[0], char_vect.size());
    

    甚至像这样:

    static_assert( std::numeric_limits<std::vector<char>::difference_type>::max() <= std::numeric_limits<std::streamsize>::max() );
    

    顺便说一句,向量中元素的最大数量是从上面以某个有符号整数类型的最大值为界的std::vector<some_type>::difference_type。这是因为该方法max_size()返回的值等于distance(​begin(), end())某个最大可能向量的值。请参阅:container.requirements.general/4。Astd::distance返回有符号整数类型的值difference_type。

    • 1

相关问题

  • 编译器和模板处理

  • 指针。找到最小数量

  • C++,关于枚举类对象初始化的问题

  • 函数中的二维数组

  • 无法使用默认构造函数创建类对象

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5