0

I know that there are a many similar questions out there on stackoverflow.com but I couldn't figure out a solution for myself. After quite some time on research, my brain is broken now even though I think the task I want to do is relatively simple.

So I have two structs:

struct files_t {
    file_t *file;
};

struct file_t {
    unsigned char *bytes;
    unsigned int len;
};
  • The first struct files_t contains a unknown amount of structs of the second struct file_t.
  • The second struct file_t contains an array of unsigned char which represents the bytes of the file_t and the length of this bytes-array.

Then I create myself a pointer to a files_t struct:

files_t* files;

My question now is: How can I iterate through this files struct pointer (Pseudocode: for each file in files) when the amount of file_t's in it is unknown at compile time and also the size of each file_t is unknown at compile time?

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Samuel Dressel
  • 1,181
  • 2
  • 13
  • 27
  • For the compiler, the first struct only contains a pointer to a `file_t` object or the the first element of an array of `file_t` object. It is up to you to manage the size of the array and use it in your loop, but the compiler will not guess it... Arrays are not first class objects in C language and *decay* to pointers to their first element, that have no way to know the size of the original array. – Serge Ballesta May 25 '20 at 15:09
  • Why would you define these structs that way? – EOF May 25 '20 at 15:11
  • @EOF Its part of a project where these structs are already defined in that way - I can't change the signature of them so I have to work with them as they are. – Samuel Dressel May 25 '20 at 15:18
  • 1
    The amount of `file_t` in `files_t` can't be unknown to your program since it will be responsible for allocating the necessary amount of `file_t`. Now if you want to keep track of how many of the allocated `file_t` have been used you will need to use a counter variable and increment it every time a next `file_t` is used. – isrnick May 25 '20 at 15:26

2 Answers2

1

The problem is not at compile time but at execution time, almost all is always unknown at compile time.

Your alone problem concerns the unknown numbers of elements in your arrays, if you have no way to have these numbers you can mark the end of each :

  • the last file_t can have its field bytes valuing NULL. I use the pointer rather than len to allow you to manage empty files
  • the last pointer in the array of files_t can be NULL
bruno
  • 32,421
  • 7
  • 25
  • 37
1

My question now is: (1) How can I iterate through this files struct pointer (Pseudocode: for each file in files) when (2) the amount of file_ts in it is unknown at compile time and also (3) the size of each file_t is unknown at compile time?

Let's start from statement (3): the good news, for you, is that the size of each file_t is absolutely known at compile time. It will be the size of a char * added to the size of an integer, and you can obtain that whenever you need it with sizeof(file_t).

Not the bad new: Since statement (2) is true (the amount of file_ts in it is unknown at compile time) unfortunately the answer to (1) is: you can't. At least, you can't without modifying something.

In order to know how many items there are in your struct files_t list (that is having a way to iterate through it) you have to options:

  1. Add a field to struct files_t containing the number of items:
    struct files_t {
        file_t *file;
       unsigned int nrOfFiles;
    };

You will take care to initialize it to 0, to increment it whenever you add a file to the list and to decrement it whenever you remove a file from it. You can iterate through it with a for loop with something like for(int i=0; i<filesList.nrOfFiles; i++).

  1. Design a sentinel value. A sentinel value is something meaning "this is the last element of the array". For example:
struct files_t {
    file_t *file;
};

struct file_t {
    unsigned char *bytes;
    unsigned int len;
};

struct file_t fileArray =
{
  { charPointer0, len01 },
  { charPointer1, len1 },
  /* ... */
  { charPointerN, lenN },
  /* Sentinel */
  { NULL, 0 }
};

struct files_t fileList = { fileArray };

In this case you can iterate until the { NULL, 0 } element is found.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39