简体   繁体   中英

C++ ifstream::read confusion

I would like to iterate through the bytes of a file stream. I am using ifstream class. When you use the read function, it copies characters from the stream into the array that I specify in the argument list. I have 3 questions.

int length = 1024;
char buff[1024];
ifstream inf(fp, ios::in | ios::binary);
inf.read(buff, length);

The reason why I do not need to use "&" before "buff" is because the first parameter is not a pointer but a reference?

And what if I have this:

int length = 1024;
vector<char> buffer;
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

What it actually does is that it takes the memory address of the first element of the vector. Only the address of the first! But it still has access to the whole array because it copies the characters into it. How is it possible? Does the same thing apply to the following as well?:

int length = 1024;
char* buffer[1024];
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

Here, how do I access the array elements?

The member function read is declared the following way

basic_istream<charT, traits>& read(char_type* s, streamsize n);

Its first parameter has a pointer type.

In this call

inf.read(buff, length);

the array buff is implicitly converted to pointer to its first element by the compiler.

So this call is equivalent to the call

inf.read( &buff[0], length);

but the last requires more typing.

If you will write

inf.read(&buff, length);

then the type of the argument will be char ( * )[1024] and the compiler will issue an error because the type of the parameter and the type of the argument are different.

As for this code snippet when a vector is used instead of the character array.

int length = 1024;
vector<char> buffer;
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

then it is invalid becuase the vector is empty.

You should write instead

int length = 1024;
vector<char> buffer( length );
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

What it actually does is that it takes the memory address of the first element of the vector. Only the address of the first! But it still has access to the whole array because it copies the characters into it. How is it possible?

The second parameter of the function specifies how the memory address of which is set by the first parameter is large.

The function could be declared for example as a template function

template <size_t N>
basic_istream<charT, traits>& read( char_type ( &s )[N] );

But in this case you will be unable to pass a pointer to a dynamically allocated array or to a part of an array.

Vectors and arrays hold their data in contiguous memory so the second element follows immediately after the first element etc. etc. So all that is needed to access the whole array/vector is a pointer to the first element and the length of the array/vector.

BTW this code is an error

int length = 1024;
vector<char> buff;
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

Because the vector buff has zero size and so there is no room to read the data. If would be ok if you wrote it like this

int length = 1024;
vector<char> buff(length);
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], length);

or better still like this (because we query the vector with the size method to see how big it is)

int length = 1024;
vector<char> buff(length);
ifstream inf(fp, ios::in | ios::binary);
inf.read(&buff[0], buff.size());

or even better like this (because we use the self-descriptive data method to get a pointer to the vector data).

int length = 1024;
vector<char> buff(length);
ifstream inf(fp, ios::in | ios::binary);
inf.read(buff.data(), buff.size());

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