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).
Related
When you pass an array to a function, does it allocate memory not for the array but for the address of the first element of the array?
All function arguments are passed on the stack (which is a memory space reserved for that purpose). Compiler optimisations might avoid stack usage by holding the values in registers, but you should work on the basis that the size of the argument is allocated to stack.
Note that in C, parameters are either integral values (int, char, etc) or pointers. Objects/Arrays are only ever a pointer to the first element/base (or pointer to pointer etc).
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.
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.
I have seen various suggestions to allocate 2D arrays in C99 with expressions like this:
int (*array)[cols] = malloc(rows * sizeof *array);
I want to know three things:
Is the entire structure allocated on the heap? Or is this actually a bunch of pointers (on the stack) pointing to arrays on the heap..?
Is the allocated memory completely contiguous?
Is it true that only one call, free(array), is needed to free the whole 2D structure? I read this somewhere - can't remember where - and it seems to work for me, but I'd like to understand why.
(1) Is the entire structure allocated on the heap? Or is this actually a bunch of pointers (on the stack) pointing to arrays on the heap..?
The entire structure (everything that malloc allocates) is on the heap.
(2) Is the allocated memory completely contiguous?
Yes, malloc allocates a contiguous region of storage.
(3) Is it true that only one call, free(array), is needed to free the whole 2D structure? I read this somewhere - can't remember where - and it seems to work for me, but I'd like to understand why.
Yes, it's true. As to the why of it, why would it be any other way? You allocate a single region of storage using malloc, and free is used to de-allocate a single region of storage that was returned by a prior malloc.
I suspect you're confused by the declaration type, though you don't mention it:
int (*array)[cols]
This means that the array variable becomes a single pointer (which is itself allocated on the stack) to an array-of-int with cols elements (which is allocated on the heap due to the use of malloc). Compare this to the more common:
int *array[cols]
... which instead declares a 1-dimensional array of pointers (where the array itself will be on the stack). You might use this latter to create an array-of-pointers-to-arrays, by storing a pointer to a series of arrays in each element (arrays which you would indeed have to allocate and free individually!). This kind of construction can be used in a similar way to a 2D array, but is not really the same thing.
Remember also that a pointer in C can always point at an array. So, even though the first declaration declares a pointer to a 1-dimensional array, it can be used to point at an array of such arrays, i.e. a 2-dimensional array as you wanted. And indeed, the malloc call allocates storage for such an array:
malloc(rows * sizeof *array);
here, sizeof *array is the size in bytes of a (single) 1D array with cols elements. When multiplied by the number of rows, it yields the storage requirement of a 2D array with size rows × cols.
C does not do hidden memory allocation. The type in the question can be used as a true 2D array. Actually it is a "pointer to array[cols] of int".
OTOH, something like int *array[cols] (note the missing parenthesis) is not a 2D array, but an "array of pointers to int". Yet even here you have to malloc the array and each row explicitly!
And for every malloc you need a corresponding free.
Note that the C standard does not require a heap, stack or any other specific management structure. This is left to the implementation. However, most hosted environments (i.e. full-sized run-time) use something like a heap.
Remember to check the result of malloc and handle allocation failure appropriately.
Does realloc function in C allocate contiguous memory space?
I am trying to implement dynamic integer array. Should I increment pointer by size of array element or by 1?
Are there any other better ways to implement dynamic array in C?
Yes, just like malloc() does.
If you have an int* ptr which is a pointer to an element of a dynamically allocated int array, a simple ptr++ will point to the next element.
Using malloc() and realloc() in C seems to me a good option for dynamic arrays.
Does realloc function in C allocate contiguous memory space?
Yes.
I am trying to implement dynamic integer array. Should I increment pointer by size of array element or by 1?
You should increase your pointer by 1.
Are there any other better ways to implement dynamic array in C?
Using malloc family functions is the only way. But in C99 and latter you can use variable length arrays (but it has some limitations as it allocates memory on stack).