简体   繁体   中英

C++ tellg() return type

I have a large binary file that I am reading and I would like to compare the current position with an unsigned long long int. However, based on the C++ documentation, it isn't clear to me if:

  1. What is the return type of tellg()
  2. How can I compare tellg() with the unsigned long long int?
  3. Is it possible that the return type of tellg() has a maximum value (from numeric_limits) that is smaller than an unsigned long long int?

Any answers or suggestions would be greatly appreciated.

Q What is the return type of tellg()?

A The return type of istream::tellg() is streampos . Check out std::istream::tellg .

Q How can I compare tellg() with the unsigned long long int?

A The return value of tellg() is an integral type. So you can use the usual operators to compare two int s. However, you are not supposed to do that to draw any conclusions from them. The only operations that the standard claims to support are:

Two objects of this type can be compared with operators == and !=. They can also be subtracted, which yields a value of type streamoff.

Check out std::streampos .

Q Is it possible that the return type of tellg() has a maximum value (from numeric_limits) that is smaller than an unsigned long long int?

A The standard does not make any claims to support it or refute it. It might be true in one platform while false in another.

Additional Info

Comparing streampos , examples of supported and unsupported compare operations

ifstream if(myinputfile);
// Do stuff.
streampos pos1 = if.tellg();
// Do more stuff
streampos pos2 = if.tellg();

if ( pos1 == pos2 ) // Supported
{
   // Do some more stuff.
}

if ( pos1 != pos2 ) // Supported
{
   // Do some more stuff.
}

if ( pos1 != pos2 ) // Supported
{
   // Do some more stuff.
}

if ( pos1 == 0 ) // supported
{
   // Do some more stuff.
}

if ( pos1 != 0) // supported
{
   // Do some more stuff.
}

if ( pos1 <= pos2 ) // NOT supported
{
   // Do some more stuff.
}


int k = 1200;
if ( k == pos1 ) // NOT supported
{
}

R Sahu did a good job on answering the questions, however I was getting overflows when storing the result of .tellg() in an int and did some extra investigation.

TL;DR: Use std::streamoff (read as "stream offset") as a integer type to store the result of tellg() .

From browsing std::basic_ifstream :

pos_type tellg();

where the pos_type is defined by the Traits template arguments, which in turn is implementation defined. For std::ifstream the Traits is std::char_traits of type char, which leads to std::fpos . Here we see:

Each object of type fpos holds the byte position in the stream (typically as a private member of type std::streamoff ) and the current shift state, a value of type State (typically std::mbstate_t).

(bolding done by me)

Hence, to avoid overflows it should be safe to cast the result of tellg() to whatever the type of std::streamoff is. Further, checking std::streamoff it says

The type std::streamoff is a signed integral type of sufficient size to represent the maximum possible file size supported by the operating system. Typically, this is a typedef to long long .


As the exact type is defined by your system, it's probably a good idea to run a quick test. Here is the result on my machine:

std::cout << "long long:" std::is_same<std::ifstream::off_type, long long>::value << std::endl;
std::cout << "long:" std::is_same<std::ifstream::off_type, long>::value << std::endl;

// Outputs
// long long:0
// long:1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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