Search code examples
cpointersdereference

How can I write this C dereferencing more succinctly?


I have a function that parses an input file into separate pages. other_func adds the lines to these pages. This is a simplified version of the function.

void func(FILE* f, page** p_pages, int* page_count) {

  ... do stuff, before passing a line struct and the current page to another function.

  page* p = *p_pages;
  int n = *page_count - 1;
  other_func(line, &p[n]);
}

In these last three lines I am trying to pass the address of the current page. I thought I could do this using something like &*p_pages[page_count - 1] but I can't seem to get it to work (getting a EXC_BAD_ACCESS error I think...).

Is there a shorter way to write those 3 lines?


EDIT: Adding more of the actual code.

/* struct declarations */

typedef struct page page;
typedef struct line line;

struct page {
  char*   title;
  char*   filename;
  page*   parent;
  line*   lines;
  int     numlines;
};

struct line {
  char  type;
  char* text;
};

/* relevant functions */

void addLineToPage(line l, page* p) {
  p->numlines++;
  p->lines = realloc(p->lines, sizeof(line) * p->numlines);
  p->lines[p->numlines - 1] = l;
}

void parse_file(FILE* file, page** p_pages, int* page_count) {
  char* rawline = 0;

  while( (rawline = p_getline(file)) ) {
    char rune = 0;
    int  n;
    sscanf(rawline, "%c %n", &rune, &n);
    remove_char(rawline, '\n');
    char* text = rawline + n;

    if (rune == '\n') {
      continue;
    } else if (!strchr(PI_RUNES, rune)) {
      *page_count = *page_count + 1;
      *p_pages = realloc(*p_pages, sizeof(page) * *page_count);

      int len = (int) strlen(rawline) + 1;
      char* fn = (char*) malloc(len * sizeof(char));
      string_to_filename(rawline, fn);
      page* p = *p_pages;
      int address = *page_count - 1;
      p[address] = (page) { .title = rawline, .filename = fn, .parent = NULL, .lines = NULL, .numlines = 0 };
    } else {
      line l = { .type = rune, .text = text };
      addLineToPage(l, *p_pages + *page_count - 1);
    }
  }
}

Solution

  • You can use &(*p_pages)[*page_count - 1] or, as alk points out, the equivalent *p_pages + *page_count - 1.

    You can derive this as follows: p is *p_pages and n is *page_count - 1, so by direct substitution &p[n] is &(*p_pages)[*page_count - 1].

    Using the fact that a[b] is *(a + b), this can be transformed to &*(*p_pages + *page_count - 1), which is just *p_pages + *page_count - 1.

    Note that there is nothing wrong with splitting it up, as you originally had, but this shows how to express it as a single expression.