将std::streampos、std::streamoff和std::streamsize转换为long long int?

10
为了测量流的位置、偏移和大小,标准指定了std::streampos、std::streamoff和std::streamsize,但它们是实现定义的。
如何以安全且可移植的方式将这些类型转换为long long int?(例如测量文件大小并将其注入一个需要long long int作为参数的函数中)
3个回答

7

对于C++98/03,不存在long long int。因此我假设你在问C++11。

streamsizestreamoff必须是整数类型的typedef(streampos不是整数,因此您不能将其传递给需要long long的任何函数)。由于整数类型是基本类型,因此它们只能由C++或编译器特定的定义来定义。

因此,唯一的问题是:这些typedef是否比long long更大?所有整数类型都可以转换为较大或相等大小的类型(有符号/无符号不论,但这里所有类型都是有符号的,所以没有问题)。但是,如果它更大......那么你会怎么做?

假设您无法更改您要“注入”到其中的函数的签名(因为如果您可以,就没有理由不直接将streamsize作为参数类型并避免问题),则没有任何选项。您有一个数据值,它比函数接受的值更大。这里没有绕过它的方法。

您可以执行静态转换为long long来关闭编译器,但如果实际大小无法适合long long,则这将无济于事。

最终,这是一个棘手的问题。您有一个函数接受一个可能过小的参数。您能做的最多就是通过static_assert检测它可能会出现问题。像这样:

static_assert(sizeof(std::streamsize) <= sizeof(long long), "Oops.");

坦率地说,我不会担心这个问题。很有可能long long是您的编译器本地支持的最大整数大小。

除了 exabytes 文件大小的情况,转换为 long long int 时会出现问题吗? - Vincent
@Vincent:不会。整数类型可以在不出问题的情况下转换为更大(或相同大小)的整数类型。 - Nicol Bolas
streampos隐式转换为streamoff,因此您可以将其传递给期望long long的某些内容。 streamposstreamoff之间的区别在于对有状态字符编码的支持。 - Potatoswatter

2
只需将值传递给需要长长整型的任何函数。 std :: streamoff和std :: streamsize都是有符号整数类型,而std :: streampos可以隐式转换为std :: streamoff。编辑:我想做一个断言,即streamsize / streamoff不会比long long更大,以防出现__int128文件大小的情况。

似乎是实现特定的,在MINGW-64 / g ++中,std :: streampos是std :: streamoff的适配器,它是一个整数类型,有符号的64位整数。 - Sam Ginrich
@SamGinrich 这不就是我所描述的吗? - Cubbi

-1

MINGW-64的简短回应: std::streampos 具有转换运算符,可将其转换为64位有符号整数类型 std::streamoff

std::streampos pos = ...;
std::streamoff ofs = (std::streamoff) pos;

例如,要查找文件的长度,您只需要打开一个std::ifstream并评估即可...

static unsigned long long getStreamSize(std::ifstream& is)
{
    std::streampos savePos = is.tellg();
    is.seekg(0, std::ios::end);
    std::streampos endPos = is.tellg();
    is.seekg(savePos);
    return (std::streampos)endPos;
}

...或者认为STL是另一个岛屿...


在C++标准中的哪里规定了tellg()返回表示从文件开头计算的字节数的整数类型?对于二进制流,is.seekg(0, std::ios::end)是未定义行为:“由basic_filebuf<charT, traits>类对象控制的序列的读取和写入限制与使用标准C库FILE进行读取和写入的限制相同。”请参见https://port70.net/~nsz/c/c11/n1570.html#note268。 - Andrew Henle
不知道你的问题要去哪里。 https://www.cplusplus.com/reference/istream/istream/tellg/ 规范是规范,用例是用例, 这次是不相交的。 - Sam Ginrich
cplusplus.com不仅不是参考资料,实际上也不是非常准确的。仅仅因为cplusplus.com说了某些事情并不意味着它是正确的。cplusplus.com有什么问题? - Andrew Henle
你也陷入了一个误区,认为与文件相关的整数值一定是文件大小。 - Andrew Henle
最终有了希望的地平线:我们在 C++ 2020 中看到 std::set<> 有包含关系 ;) - Sam Ginrich
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接