Using 3d array outside a function - c

I have a function in which I make a 3D array and fill in all the values. I also have to pass a pointer to the function which will assign the memory location of the 3D array to that function so that it can be used outside of that function. Currently, I am doing something which does not seem to work, can someone guide me to the best possible resolution?
int (*arr)[4];
void assign_3D(int (*arr)[4])
{
int local[2][3][4]; //probably we should pass *local?
memset(local, 0, sizeof(int)*2*3*4); // fill the local array with numbers
arr = local;
}
printf("%d\n", arr[1][2][3]);
I know I have written horrible code above. But I am learning :).

It is not possible to assign arrays. You are also using the wrong type for the argument (int (*)[5] is not what a int [2][3][4] decays into, use int (*)[3][4] as the argument type). Once you have the correct type, you can use memcpy() to do the assignment:
#include <string.h>
#include <stdio.h>
int arr[2][3][4];
void assign_3D(int (*arr)[3][4]) {
int local[2][3][4];
memset(local, 0, sizeof(local)); //pass local here, because it is not a pointer but an array. Passing *local would only initialize the first element of the array, i. e. the first 2D slice of it.
// fill the local array with numbers
memcpy(arr, local, sizeof(local));
}
int main() {
assign_3D(arr);
printf("%d\n", arr[1][2][3]);
}
But you can also return a newly allocated array from your function:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef int arrayType[2][3][4];
arrayType* create_3D() {
arrayType* result = malloc(sizeof(*result)); //here we need to dereference because result is a pointer and we want memory for the array, not the pointer.
memset(result, 0, sizeof(*result));
(*result)[1][2][3] = 7; // fill the local array with numbers
return result; //that's easy now, isn't it?
}
int main() {
arrayType* array = create_3D();
printf("%d\n", (*array)[1][2][3]);
free(array); //cleanup
}
Edit:
You mention that the size of the first dimension is not know before the function is run. In that case, you have to use the malloc() approach, but a bit differently:
#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
typedef int sliceType[3][4];
sliceType* create_3D(size_t* firstDimSize) {
*firstDimSize = 2;
size_t arraySize = *firstDimSize*sizeof(sliceType);
sliceType* result = malloc(arraySize);
memset(result, 0, arraySize);
result[1][2][3] = 7; // fill the local array with numbers
return result;
}
int main() {
size_t firstDim;
sliceType* array = create_3D(&firstDim);
printf("%d\n", array[1][2][3]);
free(array); //cleanup
}

There are two different ways to allocate a 3D array. You can allocate it either as a 1D array of pointers to a (1D array of pointers to a 1D array). This can be done as follows:
int dim1, dim2, dim3;
int i,j,k;
int *** array = (int ***)malloc(dim1*sizeof(int**));
for (i = 0; i< dim1; i++) {
array[i] = (int **) malloc(dim2*sizeof(int *));
for (j = 0; j < dim2; j++) {
array[i][j] = (int *)malloc(dim3*sizeof(int));
}
}
Sometimes it is more appropriate to allocate the array as a contiguous chunk. You'll find that many existing libraries might require the array to exist in allocated memory. The disadvantage of this is that if your array is very very big you might not have such a large contiguous chunk available in memory.
const int dim1, dim2, dim3; /* Global variables, dimension*/
#define ARR(i,j,k) (array[dim2*dim3*i + dim3*j + k])
int * array = (int *)malloc(dim1*dim2*dim3*sizeof(int));
To access your array you just use the macro:
ARR(1,0,3) = 4;

Related

How to reassign a array in c?

#include <stdio.h>
#include <stdlib.h>
void reasi(char** a){
char* x[] = {"1","22","333"};
a = x;
}
int main(){
char* a[] = {"bob","alice","tom"};
reasi(a);
for(int i=0; i< 3; i++){
printf("%s\n",a[i]);
}
}
The desired output should be {"1","22","333"}, but it won't work if I assign the value like that. I do know how to change the value of an int or char but don't know how to reassign the value to an array (without dynamically allocating memory). I tried to update each element inside "a" and it works. Thank you.
What you're doing won't work. You're simply creating a local array and then assigning your local parameter a to the beginning of this array (which changes nothing about the a in main). So the real thing isn't modified.
To actually modify this, you can either do a plain for loop:
// NOTE: this assumes array has the same number of elements as x
void reasi(char** a)
{
char* x[] = {"1","22","333"};
for (unsigned i = 0; i < sizeof x / sizeof *x; ++i)
a[i] = x[i];
}
Or use memcpy:
#include <string.h>
// NOTE: this assumes array has the same number of elements as x
void reasi(char** a)
{
char* x[] = {"1","22","333"};
memcpy(a, x, sizeof x);
}
Your array is not a 2D array. By seeing your code I assume you mistaken 1D array for 2D array, hence I will answer according to it
#include <stdio.h>
#include <stdlib.h>
void reasi(char** a){
a[0] = "1";
a[1] = "22";
a[2] = "333";
}
int main()
{
char* a[] = {"bob","alice","tom"};
reasi(a);
for(int i=0; i< 3; i++)
{
printf("%s\n",a[i]);
}
}
This will give you your desired output.
In C an array has a fixed size. You cannot resize it after the fact. If the size always stays the same, you can copy the new array:
#include <stdio.h>
#include <string.h>
void reasi(char const **a) {
char const *x[] = {"1", "22", "333"};
memcpy(a, x, sizeof x);
}
int main() {
char const *a[] = {"bob", "alice", "tom"};
reasi(a);
for (int i = 0; i < 3; i++)
puts(a[i]);
}
If you do want to resize the array, you are going to have to allocate it dynamically with malloc.
Both a and x are each an array of pointers to char. In C, you cannot assign the contents of an array C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) "the array object ... is not an lvalue."
Instead, you must assign each element (pointer) from x to a or use memcpy() to accomplish the same.
Further, hardcoding the contents of x in your function makes little sense. Why? You have just written a function that does nothing but assign the pointers (to String-Literals "1", "22", "333") and is incapable of doing anything else -- useful.
Why not declare x in main() and pass it as a parameter along with a and the number of elements? That way, you can pass any array of pointers to char as x (with at least 3 elements) and reassign the elements to a).
For example:
#include <stdio.h>
void reasi (char **a, char **x, size_t nelem)
{
for (size_t i = 0; i < nelem; i++) {
a[i] = x[i];
}
}
int main() {
char *a[] = {"bob","alice","tom"},
*x[] = {"1","22","333"},
*y[] = {"4","55","666","7777","8888"};
size_t n = sizeof a / sizeof *a;
reasi (a, x, n);
puts ("x->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
reasi (a, y, n);
puts ("\ny->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
reasi (a, y + 2, n);
puts ("\ny+2->a");
for (size_t i = 0; i < n; i++) {
printf ("%s\n", a[i]);
}
}
The refactoring above generalizes your reasi() function, making it reusable and a bit more useful than a single use case of "1", "22", "333".
Example Use/Output
Running you get the expected:
$ ./bin/reasi
x->a
1
22
333
y->a
4
55
666
y+2->a
666
7777
8888
Wrapping memcpy() in a function in that case wouldn't buy you any benefit, you could simply call memcpy (a, x, n * sizeof *a); from main() and avoid the function call overhead (which a decent compiler would likely optimize out anyway).
Look things over and let me know if you have further questions.

C: ERROR After mallocing and passing 2D char array to function

I don't understand what is wrong with the code below. It should malloc a 2D char array[5][30] (referred as LENGTH), pass it to a function and fill it with a string. It works just fine in the function; I can print it from there without any problem. But i cannot print even the first one from within the main() function (the application crashes if I try).
Could somebody please explain what I am doing wrong?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LENGTH 5
void fillArray(char array[][LENGTH]) {
for (int i = 0; i < 5; i++) {
strcpy(array[i],"Hi World");
}
for (int i = 0; i < 5; i++) {
printf("%s\n",array[i]);
}
}
int main() {
char** array = (char**)malloc(5*sizeof(char*));
for (int i = 0; i < 5; i++) {
array[i] = (char*)malloc(LENGTH);
}
fillArray(array);
printf("%s",array[0]);
getchar();
return 0;
}
From main() function you are passing double pointer array and catching with 2D array array[][LENGTH] which is not correct, just saying double pointer is not similar to 2D array & vice versa.
for your task in fillArray() use array of char pointer as a argument, how many ? LENGTH.
void fillArray(char *array[LENGTH]) { /* this is okay */
for (int i = 0; i < 5; i++) {
strcpy(array[i],"Hi World");/*now in `array[i]` you can store any no of char. */
}
for (int i = 0; i < 5; i++) {
printf("%s\n",array[i]);
}
}
Also casting malloc() is not required And once job is done at last don't forget to free the dynamically allocated memory by calling free() for each.
The basic problem is that your function expects a 2 dimensional array but that is not what you pass to the function.
In main you allocate a 1 dimensional array of pointers. Then for each of these pointers, you allocate a 1 dimensional array of chars. That is not a 2D array.
So your function doesn't get what it expects and therefore your program fails.
So instead of:
char** array = (char**)malloc(5*sizeof(char*));
for (int i = 0; i < 5; i++) {
array[i] = (char*)malloc(LENGTH);
}
try this:
char (*array)[LENGTH] = malloc(5*LENGTH*sizeof(char*));
to get a correctly malloc'ed 2D array.
BTW:
I think you have a bug here
#define LENGTH 5
^
I guess you want 30 instead of 5

Reading 2d array from binary file and return the pointer this array (in C)

I am trying to write a function that returns the pointer of 2d array read from a binary file. Although I compile without error there is always a segmentation fault, when I try to print one of the elements of the array. Here my code:
double ** readArray(int rows, int cols)
{
int i;
double **myArray=malloc(rows*sizeof(double*));
if (myArray){
for (i=0; i < rows; i++)
{
myArray[i]=malloc(cols*sizeof(double));
}
}
FILE *data;
data=fopen("matrix.bin", "rb");
fread(myArray,sizeof(double),rows*cols,data);
return myArray;
}
int main ()
{
int cols = 7;
int rows = 15;
double **myArray=readArray(rows, cols);
printf("%f\n", myArray[1][0]);
return 0;
}
The problem is that there is no 2D array in your code. The pointer-to-pointer look-up table thing is not a 2D array. It is [rows] number of segments scattered all over the heap, at random places. It is therefore also needlessly slow.
Also, you should keep memory allocation and algorithms separated.
Do something like this instead:
#include <stdio.h>
#include <stdlib.h>
void* allocArray (int rows, int cols)
{
return malloc( sizeof(double[rows][cols]) ); // allocate 1 2D-array
}
void readArray (int rows, int cols, double array[rows][cols])
{
FILE *data;
data=fopen("matrix.bin", "rb");
fread(array, sizeof(double[rows][cols]), 1, data); // read 1 2D-array
}
int main ()
{
int cols = 7;
int rows = 15;
double (*myArray)[cols] = allocArray(rows, cols);
readArray(rows, cols, myArray);
printf("%f\n", myArray[1][0]);
free(myArray); // free 1 2D-array
return 0;
}
The reason for the peculiar declaration double (*myArray)[cols] instead of the more logical double (*myArray)[rows][cols], is that we want to avoid the inconvenient array pointer de-referencing syntax. (*myArray)[1][0] is not easy to read. So instead of declaring an array pointer to a 2D array, declare an array pointer to a 1D array, then use pointer indexing on that array pointer. For any pointer, any_pointer[n] gives pointed-at item number n. Array pointers are no difference, so you get 1D array number n.
Your fread() call is overwriting all those pointers you painfully set up.
You need to read a single row at a time, and use the set-up pointer to store to:
for(size_t i = 0; i < rows; ++i)
fread(myArray[i], cols * sizeof *myArray[i], data);
Also, when doing I/O and memory allocation you should check the return values too, of course.

How to initialize an array with values to later be realloced in C

I've got about 12000 pre known values that I need to place in an array early in the program. Given certain circumstances, I will later need to resize this array with realloc. Is there any way to initialize an array with malloc/calloc with values, or fill an array with several other values?
You cannot initialize a malloced array this way, your best chance is to have it statically in your program, and copy it to a malloced array at the beginning of the run, e.g.:
static int arr[] = {1,2,3,4};
static int * malloced_arr;
// in the init function
malloced_arr = malloc(sizeof(arr));
if (malloced_arr)
{
memcpy(malloced_arr, arr, sizeof(arr));
}
This is the sort of thing that zero length arrays are useful for. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct values {
int x[4];
int y[0];
} V = { {1, 2, 3} };
int
main( int argc, char ** argv )
{
int *t;
int i;
struct values *Y;
(void) argc; (void) argv;
/* Allocate space for 100 more items */
Y = malloc( sizeof *Y + 100 * sizeof *Y->y );
t = Y->x;
memcpy( Y, &V, sizeof V );
t[3] = 4;
for( i = 0; i < 4; i++ )
printf( "%d: %d\n", i, t[ i ]);
return 0;
}
Of course, this is really just a parlor trick that gains you nothing over Binyamin's solution, and introduces a lot of totally unnecessary obfuscation.

Function with return type array in C

I have the following function in C:
int[] function(int a){
int * var = (int*)malloc(sizeof(int)*tags);
....
}
*var is it a pointer to an array var?
If yes, how can I return the array (var) in the function?
You can't really return an array from a function, but a pointer:
int * function(int a){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
This code below could clarify a bit how array and pointers works.
The function will allocate memory for "tags" int variables, then it will initialize each element with a number and return the memory segment that points to the array.
From the main function we will cycle and print the array element, then we will free the no longer needed memory.
#include <stdio.h>
#include <stdlib.h>
int *function(unsigned int tags) {
int i;
int *var = malloc(sizeof(int)*tags);
for (i=0; i < tags; i++) {
var[i] = i;
}
return var;
}
int main() {
int *x;
int i;
x = function(10);
for (i=0; i < 10; i++) {
printf("TEST: %i\n", x[i]);
}
free(x); x=NULL;
return 0;
}
How about:
int* function(int tags){
int * var = malloc(sizeof(int)*tags);
//....
return var;
}
Arrays and pointers to the base element type are (mostly) synonymous in C/C++, so you can return a pointer to the first element of an array and use that as if it was the array itself.
Note, your code has an input parameter a, but using tags to allocate the memory for the array. I assumed in the above code that you wanted to use the input parameter for that purpose
Also, you will have to call free() on the pointer returned by function above, when you are no longer using the array, to avoid memory leaks. malloc above allocates memory enough to hold tags number of ints, so the array is equivalent to int var[tags];
UPDATE: removed cast for malloc's return
In C, functions cannot return array types. For your purposes, you want to return a pointer to int:
int *function(int a)
{
int *var = malloc(sizeof *var * tags); // where is tags defined?
// are you sure you don't mean a here?
...
return var;
}
This will allocate a block of memory large enough to hold tags integer values and assign the address of the first element of that block to var. Note that var is a pointer to int, not a pointer to an array of int. That pointer is what gets returned from the function.
You can use the subscript oprerator on a pointer expression as though it were an array, like so:
int a = ...;
int *arr = function(a);
...
arr[0] = 0;
arr[1] = 1;
...
arr is a pointer expression, not an array expression, so sizeof arr will return the size of the pointer type, not the size of the block of memory that it points to (because of this, you will want to keep track of the number of elements you allocated separately).
In C an array is basically the same type as a pointer to an element of the array.
So char[] is basically char*
Don't forget to keep track of the size of the array, also I noticed that tags seems to be a global variable, most of the time it's a good idea to avoid global variables
Here is some example code:
#include <stdio.h>
#include <stdlib.h>
int* foo(size_t arrSize){
int* arr = (int*) malloc(sizeof(int)*arrSize);
return arr;
}
int main (int argc, char** argv){
printf("Printing array:\n");
int* arr = foo(42);
for(int i=0; i <42; i++){
arr[i]=i;
}
for (int i=0; i < 42; i++){
printf("Element: %d: %d\n", i, arr[i]);
}
free(arr);
return 0;
}

Resources