1

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?

Patrik Nusszer
  • 460
  • 3
  • 13
  • 1
    A `std::vector` guarantees that all elements are one after another in memory (exactly like for elements of an array). That is the reason for which knowing the address of first one and the count is enough to fill the vector. – 6502 Aug 19 '19 at 16:03

2 Answers2

1

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • "The second parameter of the function specifies how the memory is large address of which is set by the first parameter." Is there a typo? Also, could you write a more detailed explanation to that part? I can not replay understand that sentence clearly. – Patrik Nusszer Aug 19 '19 at 16:11
  • @PatrikNusszer The function has two parameters. The first specifies the address of the memory and the second parameter specifies its size. What is unclear? – Vlad from Moscow Aug 19 '19 at 16:14
1

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());
john
  • 85,011
  • 4
  • 57
  • 81
  • Thanks, but when you pass the memory address of the first element, how will the function access the other elements of the array? – Patrik Nusszer Aug 19 '19 at 16:19
  • 2
    @PatrikNusszer Because by definition a vector holds it's data in *contiguous memory* so the second byte follows immediately after the first byte etc. vectors and arrays are the same in this regard. – john Aug 19 '19 at 16:20
  • Okay, then please put that comment into the answer because it was a crucial part of my question and is not trivial for newbies – Patrik Nusszer Aug 19 '19 at 16:20