tags:

views:

107

answers:

6

I am trying to represent a HD page in a struct. The code below does not work, because page_size is not a constant.

int page_size = 4096;

struct page {

  char data[page_size];

  /* some methods */
}

Since I am building and randomly accessing arrays of pages, it would be nice if I could treat a page as a fixed length struct of size page_size. If possible, I would like to read page_size from a configuration file at the start of the program, or get it from the OS (e.g., GetDiskFreeSpace() on Windows). Obviously, there are only a handful of realistic page sizes, but I can't think of a way to exploit that.

Any help is appreciated.

Frank

+5  A: 

{C++}

If you want size to be determined at runtime why can't you use std::vector ?

int page_size = 4096; //or any variable

class page{

    std::vector<char> PAGE;
    public:

    page():PAGE(page_size){}
};
Prasoon Saurav
I totally missed this answer. I'll remove mine and upvote this one.
Default
+4  A: 

Nope. As you've found out, you can't. The compiler needs to know the size of its data structures, reliably and constantly, to do its work.

I'm assuming that the page data is not the only content of your struct. You probably have some header / management information about your page in there along with the text.

The common solution would be for your struct to contain a char * pointing at the actual text. That text could then be in a chunk of memory malloc()'d or calloc()'d to whatever size you need. Alas, this means you'll have to remember to move the external text around along with your struct whenever you do operations that move the struct around, and memory manage the text when you get rid of the struct... the usual C headaches.


EDIT

There are sensible "standard" ways to do this kind of thing. Here is a suggestion:

typedef char *page_ptr;
int page_size = discover_page_size();
int max_page_count = discover_max_page_count();
int pages_stored = 0;
page_ptr *page_pointers = calloc(max_page_count, sizeof(page_ptr));
char *pages = calloc(max_page_count * page_size, sizeof(char));
page_pointers[0] = pages;
int i;
for (i=1; i<max_page_count; i++) {
    page_pointers[i] = page_pointers[i-1] + page_size;
}

Now you can treat page_pointers as an array of pages, doing stuff like

read(filedesc, page_pointers[page_count++], page_size);

or

memmove(page_pointers[69], page_pointers[42], page_size);

You have an overhead of one pointer per page (surely acceptable), and your pages are physically contiguous in memory. What more could you ask? :)

Carl Smotricz
Hi, thanks. There are no other data members, only a few methods in page. If I build an array of pages, I have a continuous area of chars (e.g. 16,384) in memory.
Frank
If a struct only contains one data member, then it doesn't make sense to use a struct. Howzabout a `char[][]` ?
Carl Smotricz
It's very convenient to have methods right available for each page. But I am starting to realize that for the additional flexibility, I might have to give up some of the convenience...
Frank
I've updated my answer to include suggested coding for a very C-like solution that doesn't even require any object orientation. See how you like it!
Carl Smotricz
That's a good point. In fact, I have used this technique it in other parts of my program. I'll check if there are some hurdles I am currently not seeing... Thanks.
Frank
A: 

C and C++ requires array lengths to be compile time constants. C99 introduced variable length arrays to C, but I'm not sure if you can use them in structures.

Amarghosh
+1  A: 

[C++]

You could do:

int page_size = 4096;

struct page 
{
    char *pData;
    page() : pData(new char[page_size])
    {
    }
    ~page()
    {
        delete[] pData;
    }

  /* some methods */
}

Instead.

JLWarlow
Right, except use the initializer list
Steven Jackson
@Steven Jackson, done.
JLWarlow
Thanks. I really need the memory used for an array of pages (e.g., page* ps = new page[64]) to be continuous, or I would have to rethink/rewrite some parts of the program. This solution would not guarantee this, would it?
Frank
@Frank. No, it wouldn't. But, why exactly do you need that requirement? It would make your code very brittle.
Roddy
I hope this structure is never copied...
Kaz Dragon
A: 

you can use

#define PAGE_SIZE 4096

struct page {

  char data[PAGE_SIZE];

  /* some methods */
}

And using autoconf automake you can customize PAGE_SIZE

mathk
From OP, "If possible, I would like to read page_size from a configuration file at the start of the program, or get it from the OS (e.g., GetDiskFreeSpace() on Windows)." That means `page_size` can be determined only at runtime.
KennyTM
He wants the size to be determined at runtime. (beat me to it)
Steven Jackson
A: 

If it's just text you want, the easiest way is probably

struct page {

  std::string data;

  /* some methods */
}

That's why I asked C or C++, as this isn't available in C.

Brian Hooper