Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a best practice to wrap arrays and their length variable in a struct in C?

I will begin to use C for an Operating Systems course soon and I'm reading up on best practices on using C so that headaches are reduced later on.

This has always been one my first questions regarding arrays as they are easy to screw up.

Is it a common practice out there to bundle an array and its associated variable containing it's length in a struct?

I've never seen it in books and usually they always keep the two separate or use something like sizeof(array[]/array[1]) kind of deal.

But with wrapping the two into a struct, you'd be able to pass the struct both by value and by reference which you can't really do with arrays unless using pointers, in which case you have to again keep track of the array length.

I am beginning to use C so the above could be horribly wrong, I am still a student.

Cheers, Kai.

like image 300
Kai Avatar asked Mar 19 '09 13:03

Kai


People also ask

Is it possible to have a struct with arrays?

A structure may contain elements of different data types – int, char, float, double, etc. It may also contain an array as its member. Such an array is called an array within a structure.

Can we define array inside structure in C?

For the structures in C programming language from C99 standard onwards, we can declare an array without a dimension and whose size is flexible in nature. Such an array inside the structure should preferably be declared as the last member of structure and its size is variable(can be changed be at runtime).

Can array be declared inside structure?

An array in a structure is declared with an initial size. You cannot initialize any structure element, and declaring an array size is one form of initialization.


4 Answers

Yes this is a great practice to have in C. It's completely logical to wrap related values into a containing structure.

I would go ever further. It would also serve your purpose to never modify these values directly. Instead write functions which act on these values as a pair inside your struct to change length and alter data. That way you can add invariant checks and also make it very easy to test.

like image 88
JaredPar Avatar answered Oct 15 '22 14:10

JaredPar


Sure, you can do that. Not sure if I'd call it a best practice, but it's certainly a good idea to make C's rather rudimentary arrays a bit more manageable. If you need dynamic arrays, it's almost a requirement to group the various fields needed to do the bookkeeping together.

Sometimes you have two sizes in that case: one current, and one allocated. This is a tradeoff where you trade fewer allocations for some speed, paying with a bit of memory overhead.

Many times arrays are only used locally, and are of static size, which is why the sizeof operator is so handy to determine the number of elements. Your syntax is slightly off with that, by the way, here's how it usually looks:

int array[4711];
int i;

for(i = 0; i < sizeof array / sizeof *array; i++)
{
  /* Do stuff with each element. */
}

Remember that sizeof is not a function, the parenthesis are not always needed.

EDIT: One real-world example of a wrapping exactly as that which you describe is the GArray type provided by glib. The user-visible part of the declaration is exactly what you describe:

typedef struct {
  gchar *data;
  guint len;
} GArray;

Programs are expected to use the provided API to access the array whenever possible, not poke these fields directly.

like image 45
unwind Avatar answered Oct 15 '22 12:10

unwind


There are three ways.

  1. For static array (not dynamically allocated and not passed as pointer) size is knows at compile time so you can used sizeof operator, like this: sizeof(array)/sizeof(array[0])
  2. Use terminator (special value for last array element which cannot be used as regular array value), like null-terminated strings
  3. Use separate value, either as a struct member or independent variable. It doesn't really matter because all the standard functions that work with arrays take separate size variable, however joining the array pointer and size into one struct will increase code readability. I suggest to use to have a cleaner interface for your own functions. Please note that if you pass your struct by value, called function will be able to change the array, but not the size variable, so passing struct pointer would be a better option.
like image 4
qrdl Avatar answered Oct 15 '22 14:10

qrdl


For public API I'd go with the array and the size value separated. That's how it is handled in most (if not all) c library I know. How you handle it internally it's completely up to you. So using a structure plus some helper functions/macros that do the tricky parts for you is a good idea. It's always making me head-ache to re-think how to insert an item or to remove one, so it's a good source of problems. Solving that once and generic, helps you getting bugs from the beginning low. A nice implementation for dynamic and generic arrays is kvec.

like image 2
quinmars Avatar answered Oct 15 '22 14:10

quinmars