I have a dynamic array of double with 3 dimensions eg.
customArray : array of array of array of double
In the program I set the length of each dimension separately (not rectangular array) and change it when it is needed.
I wonder if the array is stored in a compact memory portion so to save it in a stream at once like writebuffer(customArray,sizeof(customArray))
and later, load it again to the same dynamic array like
readbuffer(customArray, savedSize);
Is this possible ?
This is not actually a multi-dimensional array. This is what is known as a jagged array. The inner most dimension is contiguous but the outer dimensions are arrays of pointers.
So the elements are not stored contiguously. If you wish to write them to a file in contiguous fashion you will need to arrange that by looping over each dimension.
In pseudo code that would be:
for i
for j
for k
write(arr[i,j,k]);
Since the innermost dimension is contiguous this could be written as:
for i
for j
write(arr[i,j]);
A jagged array can have member arrays of differing length but I presume that your array has members all of the same length.
Related
I just discovered zero-length arrays and I'd like to use it for a 2d array, the advantage of these arrays is to avoid pointers inside a structure so we can just free the structure instead of having to free it's data, so it can better be used inside a container structure like a linked list for example without having to pass a destructor function, but the problem is I can't figure out how to use it for 2d arrays. I have a structure looking like this:
struct s_arg
{
int argc;
char argv[0][0];
};
But the problem is: how to keep track of each member size without another array containing sizes? Is this possible to do this with no malloc for struct members ?
No.
The only reason an array can be used with no size known is because you do not need to know the size in order to access elements. Given an array a, a[0] is at the start of the array, a[1] is one element beyond that, and so on. The location of any element a[i] can be computed without knowing the size of the array.
Naturally, for an array to exist, somebody has to allocate memory for it, and so they must know the size. So the creator of an array must know its size, but the user does not need to.
GCC allows zero-length arrays as an extension so that a structure can have an array at its end, where the memory is allocated by the creator of the structure, who knows its size. Except to support old software, this extension became unnecessary once the C standard supported arrays of unknown size (declared with no size, [], called flexible array members).
For two-dimensional arrays, the ability to use an array without knowing its size does not apply. Given a two-dimensional array of char named a, a[i][j] is located j elements after the start of a[i]. Each of those elements is a char, so calculating j char beyond a[i] is easy. And a[i] starts i elements after the start of a. But the elements of a are arrays of char. To know how big i elements is, you must know the size of the element; you must know the size of the array of char.
So a two-dimensional array cannot be used unless the size of the second dimension is known.
There are ways to use a two-dimensional array whose second-dimension size is known at run-time, including:
Use a one-dimensional array and calculating indices into it manually, as with a[i*size + j].
Use a one-dimensional array and convert its address. For example, from some structure s with member m, (char (*)[size]) s.m, which can then be used as ((char (*)[size]) s.m)[i][j]. (See other Stack Overflow questions and answers for language-lawyer issues about treating one-dimensional arrays as two-dimensional arrays.)
Also, your member name argv suggests you might want this structure to store command-line arguments passed as a parameter of main. If so, you should be mindful that the argv second parameter of main is a pointer to pointers, not a pointer to an array. The data in those strings is generally not arranged in memory for use as a two-dimensional array of char. You could copy the strings into a two-dimensional array, but that would generally be wasteful.
Are there any C compilers that have extensions to store an array in column-major order instead of the standard row-major order?
Short answer is "No".
Long answer is that storing an array in column-major order would break the one-to-one correspondence between array index operations and pointer arithmetics, and the way an N-dimension array is sliced into N-1 dimension arrays.
Consider a 10x20 array stored in column-major order. This means that cells in adjacent columns would be next to each other in memory. On the other hand, converting a pointer to array element at i, j to an element pointer must work like this:
int *p=&a[1][5];
int *q=&a[1][6];
p++;
The standard requires that p is equal q, because the two pointers point to adjacent elements. This would not be possible if array a were stored in column-major order.
In C you would have to write your own set of functions to work with such arrays. If you code in C++, however, you would have an option to implement your own multi-dimension array, and overload the parentheses operator () to work in a column-major order.
In C we have two dimensional arrays, i.e. a[m][n].
In one dimensional arrays a is a pointer to the start of the array.
What about two dimensional arrays? Does a[i] hold a pointer to the start of the i row in an array? And thus a[i] is an array of pointers that is passed to a function in the following matter function(int **a, m, n)?
Does a[i] hold a pointer to the start of the i row in an array?
No. The data of a 2D array in C is a contiguous block of elements plus some clever indexing access. But a 2D array is an array of arrays, not an array of pointers.
Formally, the a[i] holds a 1D array. This may decay to a pointer to the first element of the ith row in certain contexts, but its type is still T[n], for some type T that you have not specified.
In one dimensional arrays a is a pointer to the start of the array.
Not correct. a is an array. When you use a in an expression, it "decays" into a pointer to the first element. To better understand this, read this chapter of the C FAQ, particularly this one.
What about two dimensional arrays? Does a[i] hold a pointer to the start of the i row in an array?
No. In a 2D array, a[i] is an array, while int a[x][y]; is an array of arrays. There are no pointers anywhere.
You might be confused because C allows this syntax: int a[][N] = ...;, but that syntax merely means that the size of the array of arrays depends on the number of items in the initialization list.
Can I look at a two dimensional array as a one dimensional array of pointers, which the j index is a pointer to the array of the j row of the matrix?
For example if I have an array[4][4]. Is arr[2] the pointer to the second row array?
No. The data is continuous in memory.
arr[2] would know the size of a single array and add 2 times that to the array pointer to get to the appropriate offset.
I may be true... It is the case if you allocated it that way : How do I work with dynamic multi-dimensional arrays in C?. However, the best way to go may to use something like &arr[2][0]. Bye, Francis
Can I look at a two dimensional array as a one dimensional array of pointers, which the j index is a pointer to the array of the j row of the matrix?
Yes. But always remember that arrays are not pointers. In case of 2D array array[M][N], spaces are allocated for each of the array element array[i] (i is int here). But in case of array of pointers *array[M], you need to allocate space for each element of array.
For example if I have an array[4][4]. Is arr[2] the pointer to the second row array?
Yes. arr2 decays to the pointer to the row 2
I often use to memorize all matrixes in a single vector, because my book says it's faster to use a single vector.And the access to a matrix is slower in time.
If I have a code like this one:
int main(int argc, char **argv)
{
int mat[10][10],i;
for(i=0;i<10;i++)
mat[i][0]=99;
int *ptr=&mat[0][0];
for(i=0;i<10;i++)
{
printf("%d\n",*ptr);
ptr+=10;
}
return 0;
}
I tried to run it 4/5 times and all times prints 10 times 99.
So also matrixes are memorized in contigous positions of memory? Always?
If yes, why the access to a vector is faster?
If by 'matrix' you mean two-dimensional array, then yes they're in contiguous memory. 2D arrays in C are just arrays of arrays (row major). If by vector you mean 1D array, then there's no reason it should be faster than accessing a 2D array.
Well, arrays (in C) are stored in contiguous memory, and since that your mat is array of arrays, it also stored in a contiguous memory. I think that dereferencing by one index (when you have some separating 1D arrays) may be a little faster than dereferencing by two indexes (in matrix), but the difference is too small to worry about.
C has no multidimensional arrays like in other languages, it called them multidimensional but they are really arrays of arrays.
And C arrays are contiguous.
(C99, 6.2.5p20) "An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type."