Search code examples
c++pointersmmappointer-arithmetic

Concise pointer arithmetic for mmap


I've trying to mmap a piece of memory and then use pointer arithmetic to treat it as an array. The size of mmaped area will be changed by the application as different sizes and data types might be passed. This is what I've done so far which is working, however, I think there might be a better way.

#include <iostream>
#include <sys/mman.h>

int main(int argc, char** argv) {
    int num_ints = 10;
    int num_bytes = num_ints * sizeof(int);
    void *base =  mmap(0, num_bytes, PROT_READ | PROT_WRITE,
                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

    // Ugly way
    for(int i = 0; i < num_ints; i++)
    {
        *((int *) base + i) = i;
        std::cout << *((int *) base + i) << " " << ((int *) base + i) << std::endl; 
    }
    std::cout << std::endl; 

    // A better way
    int *ptr = (int *) base;
    for(int i = 0; i < num_ints; i++)
    {
        *(ptr + i) += i;
        std::cout << *(ptr + i) << " " << (ptr + i) << std::endl; 
    }

    // What I'm looking is base[i] = i; which leads to
    // warning: pointer of type 'void *' used in arithmetic [-Wpointer-arith]
    // error: 'void*' is not a pointer-to-object type

    munmap(base, num_bytes);
    return(0);
}

Any suggestion for a more concise way of implementing this?


Solution

  • There's not really much left, is there?

    About the only thing you can do to shorten it is std::iota(ptr, ptr+num_ints, 0). Doesn't help you a lot here since you still have that loop for printing purposes.

    A more industrial approach would be to wrap the logic in a class template, similar to std::array<T, n>. That might turn your program into

    int main(int argc, char** argv)
    {
      mmarray<int,10> ints;
      std::iota(begin(ints), end(ints), 0);
      for(int i: ints) std::cout << i << '\n';
    }
    

    The plumbing is hidden in the constructor, destructor, begin and end methods.