memcpy for multidimensional array - c

Is there a way we can copy every element from one multidimensional array to another multidimensional array by just doing one memcpy operation?
int array1[4][4][4][4];
int array2[4][4][4][4];
int main()
{
memset(&array1,1,sizeof(array1));
memset(&array2,0,sizeof(array2));
printf_all("value in array2 %d \n",array2[1][1][1][1]);
memcpy(&array2,&array1,sizeof(array2));
printf("memcopied in array2 from array1 \n");
printf("value in array2 %d \n",array2[1][1][1][1]); //not printing 1
}

Your code is correct. You should not expect the output to show you a value of 1. You should expect it to show you a value of 16843009, assuming a 4 byte int.
The reason is: you are filling array1 with bytes of value 1, not with ints of value 1. i.e. binary 00000001000000010000000100000001 (0x01010101) is being filled into all the int elements with your memset operation.
So regardless of the size of int on your machine (unless it's a single byte!) you should not expect to see the value 1.
I hope this helps.

Yes, your code should already be correct.
You have to consider memory layout when doing this. The arrays are all in one block, multi dimensional is essentially a math trick done by the compiler.
Your code says copy this memory content to the other memory block. since both share the same layout they will contain the same values.
The following code also just copies the values, but access is handled differently so you would have to think about how to get the order of elements correct.
int array1[4][4][4][4]; //elements 256
int array2[256];
int main()
{
memcpy(&array2,&array1,sizeof(array1)); //will also copy
// original access via: a + 4 * b + 16 * c + 64 * d
}

Multidimensional array in C is a flat block of memory with no internal structure. Memory layout of a multidimensional array is exactly the same as that of a 1-dimensional array of the same total size. The multidimensional interface is implemented through simple index recalculation. You can always memcpy the whole multidimensional array exactly as you do it in your code.
This, of course, only applies to built-in multidimensional arrays, explicitly declared as such (as in your code sample). If you implement a hand-made multidimensional array as an array of pointers to sub-arrays, that data structure will not be copyable in one shot with memcpy.
However, apparently you have some misconceptions about how memset works. Your memset(&array1,1,sizeof(array1)); will not fill the array with 1s, meaning that your code is not supposed to print 1 regardless of which array you print. memset interprets target memory as an array of chars, not as an array of ints.
memset can be used to set memory to zero. As for non-zero values, memset is generally unsuitable for initializing arrays of any type other than char.

Related

Overwriting an existing 2D Array in C

I'm currently writing a project in C, and I need to be able to fill a 2D array with information already stored in another 2D array. In a separate C file, I have this array:
int levelOne[][4] =
{{5,88,128,0},
{153,65,0,0},
{0,144,160,20}}; //First Array
int levelTwo[][4] =
{{5,88,128,0},
{153,65,0,0},
{0,144,160,20}}; //Second Array
And in my main file, I have this variable which I'd like to fill with the information from both of these arrays at different points in my code. (This isn't exactly what I'm doing, but it's the general gist):
#include "arrayFile.c"
void main()
{
int arrayContainer[][4] = levelOne;
while (true)
{
func(arrayContainer);
if(foo)
{
arrayContainer = levelTwo;//Switches to the other array if the conditional is met.
}
}
}
I know this method doesn't work - you can't overwrite items in arrays after they're instantiated. But is there any way to do something like this? I know I'll most likely need to use pointers to do this instead of completely overwriting the array, however there's not a lot of information on the internet about pointers with multidimensional arrays. In this situation, what's best practice?
Also, I don't know exactly how many arrays of 4 there will be, so I wouldn't be able to use a standard 3D array and just switch between indexes, unless there's a way to make a 3D jagged array that I don't know about.
Given the definitions you show, such as they are, all you need is memcpy(arrayContainer, levelTwo, sizeof LevelTwo);.
You should ensure that arrayContainer has sufficient memory to contain the copied data and that LevelTwo, since it is used as the operand of sizeof, is a designator for the actual array, not a pointer. If it is not, replace sizeof LevelTwo with the size of the array.
If you do not need the actual memory filled with data but simply need a way to refer to the contents of the different arrays, make arrayContainer a pointer instead of an array, as with int (*arrayContainer)[4];. Then you can use arrayContainer = levelOne; or arrayContainer = levelTwo; to change which data it points to.
Also, I don't know exactly how many arrays of 4 there will be, so I wouldn't be able to use a standard 3D array and just switch between indexes, unless there's a way to make a 3D jagged array that I don't know about.
It is entirely possible to have a pointer to dynamically allocated memory which is filled with pointers to arrays of four int, and those pointers can be changed at will.

C Large Two Dimensional Array Creation

****New to C!****
I am running Dev-C++ 4.9.9.2 on Windows 7 (64 bit build)
My computer has 39GB of Physical Memory.
I am trying to create a large two dimensional array. I have already created code that tells me how many dimensions it has, and how many items are in each dimension.
As an example, let's say the array is two dimensional: One million items long, and 6 wide:
[1,2,3,4,5,6],
[1,2,3,4,5,6],
[1,2,3,4,5,6],
...and on to one million items.
I have tried:
float MyArray[1000000][6];
but this crashes Dev-C. It seems to fail when I try to initialize an array larger than:
float Myarray[86486][6];
I imagine I am experiencing a "stack overflow" which amuses me since that is the name of this site.
I have been digging around and it seems I need to use malloc to help C understand how much memory to reserve. I have seen good examples of how to use this to set up a 1 dimensional array, but I would very much appreciate example code of how to set this up with a 2 dimensional array.
I have seen the example here: Initializing a large two dimensional array in C
But I'm afraid I am too much of a beginner in c to understand the brief explanation.
As background: I am coming from python where you can make an array of (almost) any size or dimension by just declaring MyArray=[] and then filling it with whatever you want.
Thank you!
Yeah, you're running up against the limit of the size of an individual stack frame.
Here's one approach:
#include <stdlib.h>
...
int main(void)
{
/**
* declare myArray as a *pointer* to a 6-element array of float
*/
float (*myArray)[6];
/**
* dynamically allocate space for 1 million objects of type
* "6-element array of float"
*/
myArray = malloc(sizeof *myArray * 1000000);
...
myArray[i][j] = ...;
}
Why this works:
The subscript operation a[i] is interpreted as *(a + i); that is, we compute the address of the i'th element (not byte) after a (the base address of the array) and dereference it. Since myArray is a pointer to a 6-element array of float, myArray[i] gives us the address of the i'th 6-element array of float after myArray.
The advantage of this approach is that the memory is allocated in a contiguous chunk, and you can subscript myArray like any 2-d array.

Passing multi-dimensional arrays to functions in C

Why is it necessary to specify the number of elements of a C-array when it is passed as a parameter to a function (10 in the following example)?
void myFun(int arr[][10]) {}
Is it so because the number of elements is needed to determine the address of the cell being accessed?
Yes. It's because arr[i][j] means ((int *)arr)[i * N + j] if arr is an int [][N]: the pointer-arithmetic requires the length of a row.
The compiler needs to have an idea when the next row starts in memory (as a 2D array is just a continuous chunk of memory, one row after the other). The compiler is not psyche!
It is only necessary if you used static allocation for your array thought. Because the generate code create a continuous memory block for the array, like pointed out ruakh.
However if you use dynamic allocation it is not necessary, you only need to pass pointers.
Regards

Dynamic Array printing

I am trying to print a dynamic array, but I am having trouble with the bounds for the array.
For a simple example, lets say I'm trying to loop through an array of ints. How can I get the size of the array? I was trying to divide the size of the array by the size of the type like this sizeof(list)/sizeof(int) but that was not working correctly. I understand that I was trying to divide the size of the pointer by the type.
int *list
// Populate list
int i;
for(i = 0; i < ????; i++)
printf("%d", list[i]);
With dynamic arrays you need to maintain a pointer to the beginning address of the array and a value that holds the number of elements in that array. There may be other ways, but this is the easiest way I can think of.
sizeof(list) will also return 4 because the compiler is calculating the size of an integer pointer, not the size of your array, and this will always be four bytes (depending on your compiler).
YOU should know the size of the array, as you are who allocated it.
sizeof is an operator, which means it does its job at compile time. It will give you the size of an object, but not the length of an array.
So, sizeof(int*) is 32/62-bit depending on architecture.
Take a look at std::vector.
There is no standardized method to get the size of allocated memory block. You should keep size of list in unsigned listSize like this:
int *list;
unsigned listSize;
list = malloc(x * sizeof(int));
listSize = x;
If you are coding in C++, then it is better to use STL container like std::vector<>
As you wrote, you really did tried to divide the size of a pointer since list is declared as a pointer, and not an array. In those cases, you should keep the size of the list during the build of it, or finish the list with a special cell, say NULL, or anything else that will not be used in the array.
Seeing some of the inapropriate links to C++ tools for a C question, here is an answer for modern C.
Your ideas of what went wrong are quite correct, as you did it you only have a pointer, no size information about the allocation.
Modern C has variable length arrays (VLA) that you can either use directly or via malloc. Direcly:
int list[n];
and then your idea with the sizeof works out of the box, even if you changed your n in the mean time. This use is to be taken with a bit of care, since this is allocated on the stack. You shouldn't reserve too much, here. For a use with malloc:
int (list*)[n] = malloc(*list);
Then you'd have to adapt your code a bit basically putting a (*list) everywhere you had just list.
If by size you mean the number of elements then you could keep it in a counter that gets a ++ each time you push an element or if you dont mind the lost cycles you could make a function that gets a copy of the pointer to the first location, runs thru the list keeping a counter until it finds a k.next==null. or you could keep a list that as a next and a prev that way you wouldnt care if you lost the beginning.

What is the reason C compiler demands that number of columns in a 2d array will be defined?

given the following function signature:
void readFileData(FILE* fp, double inputMatrix[][], int parameters[])
this doesn't compile.
and the corrected one:
void readFileData(FILE* fp, double inputMatrix[][NUM], int parameters[])
my question is, why does the compiler demands that number of columns will be defined when handling a 2D array in C? Is there a way to pass a 2D array to a function with an unknown dimensions?
thank you
Built-in multi-deminsional arrays in C (and in C++) are implemented using the "index-translation" approach. That means that 2D (3D, 4D etc.) array is laid out in memory as an ordinary 1D array of sufficient size, and the access to the elements of such array is implemented through recalculating the multi-dimensional indices onto a corresponding 1D index. For example, if you define a 2D array of size M x N
double inputMatrix[M][N]
in reality, under the hood the compiler creates an array of size M * N
double inputMatrix_[M * N];
Every time you access the element of your array
inputMatrix[i][j]
the compiler translates it into
inputMatrix_[i * N + j]
As you can see, in order to perform the translation the compiler has to know N, but doesn't really need to know M. This translation formula can easily be generalized for arrays with any number of dimensions. It will involve all sizes of the multi-dimensional array except the first one. This is why every time you declare an array, you are required to specify all sizes except the first one.
As the array in C is purely memory without any meta information about dimensions, the compiler need to know how to apply the row and column index when addressing an element of your matrix.
inputMatrix[i][j] is internally translated to something equivalent to *(inputMatrix + i * NUM + j)
and here you see that NUM is needed.
C doesn't have any specific support for multidimensional arrays. A two-dimensional array such as double inputMatrix[N][M] is just an array of length N whose elements are arrays of length M of doubles.
There are circumstances where you can leave off the number of elements in an array type. This results in an incomplete type — a type whose storage requirements are not known. So you can declare double vector[], which is an array of unspecified size of doubles. However, you can't put objects of incomplete types in an array, because the compiler needs to know the element size when you access elements.
For example, you can write double inputMatrix[][M], which declares an array of unspecified length whose elements are arrays of length M of doubles. The compiler then knows that the address of inputMatrix[i] is i*sizeof(double[M]) bytes beyond the address of inputMatrix[0] (and therefore the address of inputMatrix[i][j] is i*sizeof(double[M])+j*sizeof(double) bytes). Note that it needs to know the value of M; this is why you can't leave off M in the declaration of inputMatrix.
A theoretical consequence of how arrays are laid out is that inputMatrix[i][j] denotes the same address as inputMatrix + M * i + j.¹
A practical consequence of this layout is that for efficient code, you should arrange your arrays so that the dimension that varies most often comes last. For example, if you have a pair of nested loops, you will make better use of the cache with for (i=0; i<N; i++) for (j=0; j<M; j++) ... than with loops nested the other way round. If you need to switch between row access and column access mid-program, it can be beneficial to transpose the matrix (which is better done block by block rather than in columns or in lines).
C89 references: §3.5.4.2 (array types), §3.3.2.1 (array subscript expressions)
C99 references: §6.7.5.2 (array types), §6.5.2.1-3 (array subscript expressions).
¹ Proving that this expression is well-defined is left as an exercise for the reader. Whether inputMatrix[0][M] is a valid way of accessing inputMatrix[1][0] is not so clear, though it would be extremely hard for an implementation to make a difference.
This is because in memory, this is just a contiguous area, a single-dimension array if you will. And to get the real offset of inputMatrix[x][y] the compiler has to calculate (x * elementsPerColumn) + y. So it needs to know elementsPerColumn and that in turn means you need to tell it.
No, there's not. The situation's pretty simple really: what the function receives is really just a single, linear block of memory. Telling it the number of columns tells it how to translate something like block[x][y] into a linear address in the block (i.e., it needs to do something like address = row * column_count + column).
Other people have explained why, but the way to pass a 2D array with unknown dimensions is to pass a pointer. The compiler demotes array parameters to pointers anyway. Just make sure it's clear what you expect in your API docs.

Resources