# Brief Intro to Memory Mapping Into Structs

Learning how to memory map was a frustrating topic to hunt down, despite how easy it really is. First I'll share my main source, then get to what I was doing. For a great intro to memory mapping, follow that link. It will explain the code below while I'm just going to show it and tell what it does on a high level.

#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>

struct GamColor
{
unsigned char d_red;
unsigned char d_green;
unsigned char d_blue;
};

struct GamColorMap
{
char            d_name[16];
struct GamColor d_map[16];
unsigned int    d_ID;
};

int main(void) {

int fd, offset;
void *data;
struct stat sbuf;

if ( (fd = open("ocean.thm", O_RDONLY)) == -1) {
perror("open");
exit(1);
}

if (stat("ocean.thm", &sbuf) == -1) {
perror("stat");
exit(1);
}

offset = 0;

data = mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, offset);
perror("mmap");
exit(1);
}

struct GamColorMap *thm = malloc(sizeof(struct GamColorMap));

memcpy(thm, data, sizeof(struct GamColorMap));
offset += sizeof(struct GamColorMap);

int i;
for (i = 0; i < 16; i++) {
struct GamColor *c = &thm->d_map[i];
printf("%d %d %d\n", c->d_red, c->d_green, c->d_blue);
}

free(thm);
munmap(data, sbuf.st_size);

return 0;
}


So what the crap's going on? I have a binary file called ocean.thm, which consists of a name (maximum 16 characters, it's padded with 0's at the end), the 16 RGBx colors (the x is to keep things aligned on four byte blocks), and a 4-byte ID that is set to 0 and intended to be handled at runtime (which it's not in this example). "data" is a void pointer so I can throw whatever in there, however if you're doing pointer arithmetic (e.g. (data + offset)), make sure you cast data as a character pointer so it will always step one-byte. A use not shown is the theme file containing several ascii sprites, with each sprite containing its own frames as well. So it needs to know how much data to grab between sprites, which you can accomplish with some math involving sizeof() and total_frames * sprite_width * sprite_height * sprite_data_size. You need to keep track of the offset there, and you can loop while the offset is less than sbuf.st_size.

Other than that, the code is pretty much straightforward. It seriously took me longer than it should have to find the link I gave above: I just wanted some sample mmap code that read from a file, damn it! Anyway, it's here to help anyone who may need it.

It occurred to me that one of the reasons memory mapping into a struct seemed initially confusing was because of an initial confusement of what a struct even is: a struct is like an array with different types and names for indices. If you have a struct with int x, int y, int z in it, the struct's size is sizeof(int) * 3 bytes. Ints are usually 4 bytes, so the whole struct is 12 bytes. If you have a blob of memory 12 bytes wide, you can memcpy it directly into that struct, and then read it out in 4-byte chunks as integers. This means it's important to pad your binary data if you're generating a file to be read by C from a higher language. In Python, import struct and use pack/unpack to help out.

#### Posted on 2010-03-11 by Jach

Tags: c, programming

LaTeX allowed in comments, use $\\...\\$\$ to wrap inline and $$...$$ to wrap blocks.