Arrays vs Structures
First off, a struct
is not the same thing as an array. struct
s and arrays are different data types. They have similarities (e.g., they are both complex data types, they can group one or more values, etc.)
However, there are major differences too, including that they are used in different contexts, array members are of the same data type, while struct members do not have to be of the same data type, array elements are accessed by means of a zero-based index (e.g., using the bracket notation), while struct members may be accessed using their names (with the dot operator), and so on.
Watch the shorts on "Structures" and "Arrays" for more info!
Word-Aligning
The SO answer linked in the comment above explains that quite well. Nevertheless, let's try to simplify this a bit!
A variable is simply a location in memory. A memory location has a numerical address. When data gets read from or written to memory, this is done in word-sized chunks.
What's the size of a word? Well, that's different from one computer to another. On the CS50 IDE, the size of a word is 8 bytes (64 bits), so data gets read/written in 8-byte chunks. For that reason, when reading data, for example, it's better if that data is stored at a memory block that starts at a location whose address is a multiple of 8 (I think the multiple of 4 bit is dated?)
Getting data to be stored at a memory block that starts at a location whose address is multiple of the word size is called word-aligning. Typically, this is done by inserting some meaningless bytes, referred to as padding.
But what happens if the data is not word-aligned? In that case, the computer may have to do some extra work in order to retrieve that data. For example, suppose we want to read one byte of data from location 17. To get that, the computer would have to read the word that starts at location 16, then left-shift to get my data.
This other SO answer gives another great explanation (with visualization this time!) It assumes the size of a word is 4 bytes though, so mind that!
What does this have to do with BMPs?
Speed is not our concern here really. We're more concerned about how the data is organized in memory. A BMP viewer, for example, expects the data of the BMP to be viewed to stored exactly in that order:

To prevent the members of any of these structs from getting word-aligned (thus, some locations would change), we need to use the __attribute__((__packed__))
type attribute, per bmp.h
.