2

In Problem Set 4 we're given the copy.c and bmp.h files. On line 47 the fread() function is called with the arguments, &bf, sizeof(BITMAPFILEHEADER), 1, and inptr. I understand what each of these arguments mean: the first is the location in memory to the struct bf, second is the size, third is how many times we read it and fourth is the file pointer.

Now what I don't understand: How does the data get added to the struct in the proper order? How does every value align perfectly? In my understanding, it goes to the location (&bf) of the struct in memory, and just inserts all the numbers in a long sequence after each other and since the struct is a specific (total) size, all values get automatically aligned perfectly, since the next one starts when the last one ends. But this assumes structs are formatted like that in memory, and if this was the case, why can't I just say &bf = [long sequence of digits]? I tried this in another program and I got an error saying "expression is not assignable". So if this doesn't work, how does numbers get assigned to it's proper memory slot when using fread()?

EDIT: To clarify a bit more. When working with structs, I thought you had to specify each value individually, like bf.bfType = [type], bf.bfSize = [size], and so on... but instead we're just specifying the whole struct and the values get sorted to the right datatypes automatically.

EDIT#2: Seems my thinking was correct, but my syntax was off. The correct syntax that aligns with what I was trying to understand would be BITMAPFILEHEADER bf = {x, x, x, x, x}; for each of the values in the struct. You can't assign in this way however, only initialize, even when using the & operator. This part I don't understand. Why can fread do this but I can't manually? Is it just C syntax preventing me for whatever reason or what? I think it's not a matter of logic error any longer, but a limit of the language that I don't understand.

2 Answers 2

1

fread() knows nothing about the structure. All it knows is the size of the block to read and the address of the memory block where it will put the bytes it reads.

It's up to you to make sure that the block of data you're reading in is sensible and matches the structure that you will subsequently use to access the individual members of the BITMAPFILEHEADER called bf.

C has a special feature that allows initializaton of structs using the {} method as you've shown, but after that point, you cannot assign values directly to an entire struct at once. You can either write a block of memory (using fread() as you're doing or perhaps memcpy()) or assign values to the individual members of the struct such as bf.bfSize = 80;

4
  • Does this mean there is a special character like '\0' that signals the end of the struct? If I got this right, when we use fread() on &bf we're going to the address assigned to that struct. The total size of the struct will be all its members size added together? Since the first member has a size of 8 bits, the first 8 bits of the input will "automatically" be assigned to the first member? The next 32 bits to the second member, since it's 32 bits long. So If the input doesn't match the´sizes, the input will be formatted incorrectly, but with the correct values, if the size allows it?
    – nbh
    Aug 6, 2015 at 16:53
  • no special character at the end. When you declare BITMAPFILEHEADER bf; you get an address (&bf) that points to a block of 14 bytes (the size of the structure). fread() then reads 14 bytes from inptr and stores those bytes in the block. If you told fread() to read 20 bytes and put it there, you would be accessing memory that you aren't allowed to, so you may crash. Remember, fread() doesn't know anything about what those bytes represent. It's a straight copy.
    – curiouskiwi
    Aug 6, 2015 at 19:40
  • @curiouskiwi: sorry, I have started a question, then deleted it because I have realized my mistake
    – Vitale
    Jan 20, 2016 at 9:00
  • Does the attribute__((_packed)) matter here? In our code, we just write to a location and read from the same location, but suppose instead of reading, we said"BYTE green = triple.rgbtgreen"... could it be that the "green" part of the struct would be stored somewhere different from the 2nd byte after &triple without attribute__((_packed))?
    – Dr.Queso
    Mar 31, 2016 at 20:22
0

Maybe you'll find this useful. https://stackoverflow.com/questions/330793/how-to-initialize-a-struct-in-ansi-c some points about (ANSI) C99, some good details and some info about Compound literals

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .