2

I'm trying to read from a file and copy it to another file. I am reviewing some codes online and I seem to notice that some declare fread this way:

fread (buffer, 1, 1000, src)

some this way

fread (&buffer, 1, 1000, src)

Let's say I have already declared this:

typedef uint8_t BYTE;
BYTE buffer[1000];

How would those two be different?

M Tiz
  • 21
  • 2
  • 2
    Same value, different type. When used as function argument, `buffer` is a pointer to `BYTE` while `&buffer` is a pointer to `BYTE[1000]`. – Gerhardh Jun 29 '21 at 07:05
  • 3
    If `buffer` is an array they have the same value but different type. If `buffer` is a pointer they have different values. – Weather Vane Jun 29 '21 at 07:05
  • I forgot to place. I have typedeffed BYTE as a datatype. – M Tiz Jun 29 '21 at 07:11
  • `fread (&buffer, 1, 1000, src)` is usually wrong when `buffer` is an array or a pointer. It is right, for say `char byt; fread(&byt, sizeof byt, 1, src);` – Weather Vane Jun 29 '21 at 07:13
  • Oh. I see. I get it now. Thanks! – M Tiz Jun 29 '21 at 07:20
  • So just checking if I have it right. I don't do &buffer if buffer is an array or pointer because buffer in that case is already storing an address. – M Tiz Jun 29 '21 at 07:23
  • So just checking if I have it right. I don't do &buffer if buffer is an array or pointer because buffer in that case is already storing an address. – M Tiz Jun 29 '21 at 07:23
  • `buffer` is not **storing** an address. Instead `buffer` **is** an address – Gerhardh Jun 29 '21 at 07:28
  • @MTiz While you are correct about **not** using `&buffer` and you are correct about the case where `buffer` is a pointer, your explanation isn't strictly correct for the array case. The more correct explanation is that when an array is used in an expression, it will in most cases be implicit converted to a pointer to the first element (a few exceptions exists). But for any practical use... yes, avoid `&` and the array will automatical be converted to a pointer with the correct value. – Support Ukraine Jun 29 '21 at 07:32
  • Thanks! I'm really confused with arrays being pointers but I have an idea already that it is a pointer to the first element. Thank you for the answers! – M Tiz Jun 29 '21 at 07:34
  • Thanks! I'm really confused with arrays being pointers but I have an idea already that it is a pointer to the first element. Thank you for the answers! – M Tiz Jun 29 '21 at 07:35
  • An array *isn't* a pointer, but when you refer to the name of an array, it decays to a pointer to its first element. That's why we do `scanf("%c", &chr)` but `scanf("%s", str);` – Weather Vane Jun 29 '21 at 07:37

2 Answers2

2

&buffer returns a pointer to the array. The pointer has type BYTE (*)[1000].

When an array is used where a pointer is expected, it degenerates into a pointer to its first element, so buffer is equivalent to &(buffer[0]) in this situation. The pointer has type BYTE*.

Both pointers point to the same address.

ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Can you explain what happens on `&buffer+1` and `buffer+1`? – Paul Ogilvie Jun 29 '21 at 08:22
  • @PaulOgilvie That's a different question and should be posted as a separate one. Though I strongly suspect there are already lots of duplicates for it. – Lundin Jun 29 '21 at 08:24
  • `p+1` will advance the pointer by the size of the thing pointed (`sizeof(*p)`). If you apply what I explained in my answer, you'll realize they are very different. – ikegami Jun 29 '21 at 08:26
0

In this case, there is no difference. The specification for fread is (C17 7.21.8.1):

   size_t fread(void * restrict ptr,
   size_t size, size_t nmemb,
   FILE * restrict stream);

The fread function reads, into the array pointed to by ptr...

  • buffer when used in an expression "decays" into a pointer to the first element. It will become type uint8_t* pointing at buffer[0].
  • &buffer takes the address of the array and an expression with & as operator to an array will not make it "decay". The resulting type is a pointer to array, uint8 (*)[1000], which points at the address where the array begins. Which is also where buffer[0] is stored, so it is the same one as above.

Either of these will give the same address and either will work, as far as fread is concerned. Reading the standard pedantically, &buffer is actually more correct.


Unrelated to your question, typedef uint8_t BYTE; is horrible practice. Don't invent your own language with typedefs - by doing so you only make your code strange and less readable. Stick to the standard types as already available from stdint.h.

Lundin
  • 195,001
  • 40
  • 254
  • 396