Is there a way to use zero-length arrays with 2d arrays? - arrays

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.

Related

Explain how it's possible to allocate and free memory for a 2d array in C with just these 2 lines:

int (*mapTerrain)[10] = (int (*)[10])malloc(sizeof(int[10][10]));
free(mapTerrain);
Someone on this site suggested these 2 lines for working with dynamical 2d arrays in C. Dimensions are [10][10]. Problem is, I'm not sure I understand them correctly. If I had to explain these 2 lines I'd say the following:
On the left we have an array of int pointers with size 10. (Can't explain the casting, I myself would expect it to be int *).
What's being passed to malloc is an array of int-s sized [10][10]. (Why isn't it ...malloc(sizeof(int*10*10));?) What allows us to pass an array to malloc instead of size_t size?
As for the free(mapTerrain); line. How come one free is enough? From what I remember you have to call free for every row of a dynamical 2d array.
The cast of the result of malloc is just clutter and not necessary.
The most correct, formal version would be:
int (*mapTerrain)[10][10] = malloc(sizeof(int[10][10]));
This is an array pointer to a int [10][10] array. However, such a pointer is a bit painful to work with in practice, since to get an item we have to do:
*mapTerrain to get the array pointed at from the array pointer.
(*mapTerrain) parenthesis to not trip over operator precedence.
(*mapTerrain)[i][j] to get a single item.
As a trick, we can instead use a pointer to the first element of the int[10][10]. The first element is of type int[10], and so an array pointer to that element is int(*)[10]. With this type, we can do mapTerrain[i][j] as expected, because i means "give me array number i" through pointer arithmetic.
This trick is essentially the same thing as when we do something like
char* ptp = malloc(sizeof("hello"));`
Here we don't point to the whole array either, we point at the first element of it.
sizeof(int[10][10]) is 100% equivalent to sizeof(int*10*10) (or 400 for that matter), but the first is self-documenting code, showing that we are expecting to use the allocated data as an array int[10][10].
One free is enough because there is just one malloc. You allocate the whole 2D array as a contiguous chunk of memory.
Further reading: Correctly allocating multi-dimensional arrays.

How to determine the number of array elemnts in C?

I have a function in C (I am using gcc 4.8.0) which receives an array as its argument. Is there a way to accurately determine the number of elements in the array, without passing an additional argument array_count?
There is no way to determine in general the number of array elements passed as parameter.
When you pass a array as argument in C, you only pass the pointer to that array, that is the pointer to the first element (indexed 0) of the memory zone holding that array.
Very often, programmers have the convention of passing, as another argument, the size of that array. For example, the standard qsort(3) library function is expecting, as its second nmemb argument, the number of elements in the array to be sorted.
Alternatively, you might use flexible array members, e.g. pass (in C99, not in earlier C standard) address of structures like
struct my_flexarray_st {
int size; // allocated size
int len; // used length, should be less than size
double arr[]; /// only len numbers are meaningful
};
Whatever method you use, you need to understand that array sizes are conventionally known by functions when passed by argument. So please, document that convention. You could even have the (bad) convention that all arrays have some global variable as their dimension.
For heap allocated memory zones, the standard gives you malloc, calloc and friends to get such fresh zones, but no way to query their allocated sizes. Some C libraries have non-standard extensions to query that (but I don't recommend using them).
In recent C++11 (which is not the same as the C language) you might be interested by std::vector and std::array template containers.
Arrays decay into pointers in function arguments so size cannot be determined.
An lvalue [see question 2.5] of type array-of-T which appears in an expression decays (with three exceptions) into a pointer to its first element; the type of the resultant pointer is pointer-to-T because an array is not a "modifiable lvalue,"
(The exceptions are when the array is the operand of a sizeof or & operator, or is a literal string initializer for a character array.)
You can't , unless the array is static (i.e. not dynamic-allocated) , then you can use sizeof operator.
Not possible. This is why you either use a data structure like a linked list where you can actually determine the length or you require a length argument in your function.
Even with the required length argument alone there is no way to know it is true.
So, your API should also require a standard sentinel value to terminate the array.
Generally this could be NULL or something but depends on your array type.
This is doable in C. You can query size of array if you are in the same scope of its definition via sizeof. If you are in scope of function which takes array as parameter you need to declare the parameter as pointer to array (not just as array - in this case array will decay to pointer to first element), in this case size of array would be saved during argument passing:
void foo(int (*param)[3] ) { assert (sizeof(*param) == sizeof(int)*3; }
However, if you mean by "array" pointer to some dynamically allocated memory with not-known at compile time size, then you definetely need to pass size separately.
you can do a while look
function(arr[])
{
/* not this is pseduo code */
int i = 0;
while (*arr[i++] != null)
{
}
// i is number of elements
}

How an n-dimensional (n>=2) array is represented in memory?

Can anyone provide me with a formula so that I can understand the memory representation of an n-dimensional(n>=2) array like this "How_are_two-dimensional_arrays_represented_in_memory"?
This calculation is applicable for 2D-arrays only.
How to calculate, suppose, a 5D array?
Ok....
I think I found the answer: Array_data_structure#Two-dimensional_arrays
A 2-dimensional array in C is nothing more or less than an array of arrays. A 3-dimensional array is an array of arrays of arrays. And so on.
The relevant section from the C99 standard is 6.5.2.1, "Array subscripting":
Successive subscript operators designate an element of a
multidimensional array object. If E is an n-dimensional array
(n ≥ 2) with dimensions i × j × . . . × k, then E (used as
other than an lvalue) is converted to a pointer to an (n −
1)-dimensional array with dimensions j × . . . × k. If the unary *
operator is applied to this pointer explicitly, or implicitly as a
result of subscripting, the result is the pointed-to (n −
1)-dimensional array, which itself is converted into a pointer if used
as other than an lvalue. It follows from this that arrays are stored
in row-major order (last subscript varies fastest).
Some confusion is caused by the fact that the indexing operator is defined in terms of pointer arithmetic. This does not imply that arrays are "really pointers" -- and in fact they very definitely are not. Declaring an array object does not create any pointer objects at all (unless of course it's an array of pointers). But an expression that refers to the array usually (but not always) "decays" to a pointer to the array's first element (that's a pointer value, not a pointer object).
Now simple array objects, of however many dimensions, are quite inflexible. Prior to C99, all array objects had to be of a fixed size determined at compile time. C99 introduced variable-length arrays (VLAs), but even so a VLA's size is fixed when it's declared (and not all compilers support VLAs, even 12 years after the C99 standard was issued).
If you need something more flexible, a common approach is to declare a pointer to the element type, and then allocate an array using malloc() and have the pointer point to the array's first element:
int *ptr = malloc(N * sizeof *ptr);
if (ptr == NULL) /* handle allocation failure */
This lets you refer to elements of the heap-allocated array using the same syntax you'd use for a declared fixed-size array object, but in arr[i] the expression arr decays to a pointer, whereas in ptr[i] `ptr is already a pointer.
The same thing can be extended to higher dimensions. You can allocate an array of pointers, and then initialize each pointer to point to the beginning of an allocated array of whatever.
This gives you something that acts very much like a 2-dimensional (or more) array, but you have to manage the memory yourself; that's the price of the greater flexibility.
Strictly speaking, this is not a 2-dimensional array. A 2-dimensional array, as I said above, is only an array of arrays. It's probably not entirely unreasonable to think of it as a 2-D array, but that conflicts with the usage in the C Standard; it's similar to referring to a linked list as a 1-D array.
The comp.lang.c FAQ is a good resource; section 6, which covers arrays and pointers, is particularly excellent.
A 2 dimensional array is really an array of pointers to arrays. A 2-dimensional array of integers a[i][j] will take up i*sizeof(int*) for the array of pointers, and i*j*sizeof(int) for the final array.
A 3-D array a[i1][i2][i3] is an array of pointers to arrays of pointers to arrays. The first level of arrays contains i1 pointers, the second level contains i1*i2 pointers, the third level contains i1*i2*i3 integers.
In general, an N-dimensional array with sizes i1..iN will have N-1 levels of arrays of pointers and 1 level of arrays of ints. The arrays in level N have length iN and there are product of i1..iN-1 arrays in that level.
So, a 5-D array:
1 array, length i1, of pointers
i1 arrays, length i2, of pointers
i1*i2 arrays, length i3, of pointers
i1*i2*i3 arrays, length i4, of pointers
i1*i2*i3*i4 arrays, length i5, of ints
Hope that helps (and I hope I got the indices right).
That wikipedia link you posted refers to a /different kind of multidimensional array/. By default, C multidimensional arrays are the way I just described. You can also abstract them as a single dimensional array. This saves memory and makes the entire array contiguous, but it makes accessing elements somewhat more complex. For the 5-D example:
// WARNING I AM CHANGING NOTATION. N1..N5 are the lengths in each direction.
// i1..i5 are the indicies.
int* bigarray = malloc(sizeof(int)*N1*N2*N3*N4*N5);
// now instead of bigarray[i1][i2][i3][i4][i5], write this:
*(bigarray + i1*N2*N3*N4*N5 + i2*N3*N4*N5 + i3*N4*N5 + i4*N5 + i5);
each term there is an offset times the number of elements we need to offset. For example, to increment by one first-dimension level we need to traverse the the four remaining dimensions once to 'wrap around', if you will.
How arrays are stored in memory for C is not, as I recall, standardized. But for some information about arrays, and how they might be stored in memory, see the following two links:
http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html
http://publications.gbdirect.co.uk/c_book/chapter5/arrays.html
The first link is more general, and discusses different ways of storing arrays, while the second discusses the most likely way a C array may be layout in memory.

Array of pointers

I am trying to construct an m-way tree and I am having trouble visualizing an array of pointers pointing to different instances of the B_tree node class (this basically creates the array type nodes and includes all functions associated with the tree such as count, insert etc)
Are there any tips/tricks to visualizing an array of pointers for this case? Are there any good links/resources for explanation of array of pointers? (I did not find the common search results on google that helpful)...
Here is a picture of an array of pointers, they aren't pointing to anything, but this is a visualization of an array of pointers. Here is a link explaining arrays of pointers http://ee.hawaii.edu/~tep/EE160/Book/chap9/section2.1.4.html. Enjoy.
Array with pointers is just like a usual array with a maximum number of size. Each position of the array it does not hold an integer or float or char or a struct. It holds a pointer.
What a pointer is ?
Imagine the computer's memory like a huge array which hold different kind of values. The variable which holds the pointer what it actually holds is the address of a block of memory. It does not hold the value of an integer but if you have int *a; , it means that the variable a which is store in a memory address hold the address of something which is integer.
The pointer always holds 4 bytes. Therefore an array with pointers means that each positions shows the memory address of something. If you have an integer array with pointers of size 10, means that each position shows the address of a memory block( this block stores an integer). So the array holds 10 pointers and each one of them shows to an integer.

How do I (deep) copy an array in C?

Refering to http://www.devx.com/tips/Tip/13291, it says that I can use memcpy with the size to copy determined by sizeof(), however, isn't the array pointing to a pointer?
Other than iterating through the array, how can I use memcpy to deep copy an array?
Thanks!
In the linked example int weekly_hours[5][5]; allocates space for 25 integers. There is no further indirection, so you can safely use memcpy to duplicate it's values.
A multi-dimensional array is contiguously allocated. An array of pointers (of pointers...) is a different thing (and each sub-pointer should be allocated/copied/freed on its own).
Do not be confused by the fact that an unidimensional array and a single pointer can be used interchangeably in most situations, because they are not technically the same.
To hopefully clear up some of the confusion:
An array is a chunk of allocated,
adjacent memory cells.
An array variable name can transform ("decay") into a pointer to the first element of the array, but not the other way around. This is done implicitly each time you use the array variable name in pointer arithmetics.
You can use the sizeof() operator on the variable name of any statically alloced array, to get the number of bytes in the array. If sizeof() is used on a statically allocated, multi-dimensional array, the same applies.
If you use the sizeof() operator on a
pointer, you will get the size of a
pointer (i.e. 4 bytes on a 32-bit
machine).

Resources