Declaring global variable (array) inside a function in C - c

I need to declare a global two-dimensional array in C.
The size of the array is determined by the width and height of a given picture.
So I first have to load the picture, and only then create the array. But if I want a variable (in this case, my array) to be global, I have to declare it at the top of the file and not inside a function.
So how can I declare a array as global when I only know its size after the execution of the main() function?
EDIT:
(I've also tried the other solutions so this comments refers to all of them)#Mimisbrunnr
First, thanks for the quick response!
I've tried but I can't see to make it work. I'm probably missing something stupid, but how does "array" becomes global? It says on test() that 'array' is undeclared
int *buffer;
int main() {
int i;
int x_size=100;
int y_size=100;
int * buffer = malloc(sizeof(int)*x_size*y_size);
int ** array = malloc(sizeof(int*)*y_size);
for(i = 0; i<y_size; i++) {
array[i]=&buffer[i*x_size];
}
array[0][1] = 5;
test();
return 0;
}
void test(){
printf("%d",array[0][1]);
}

create a global pointer and then malloc the space into it.
char * buffer;
int main(void) {
buffer = malloc( /* Width * Height */ );
}

I didn't actual execute this code, but this should get you started.
int x_size = 100;
int y_size = 100;
int ** array;
array = malloc(sizeof(int *)*y_size);
for(int i = 0; i<y_size; i++)
array[i] = malloc(sizeof(int)*x_size);
larsmans made a good point.
what about this?
int x_size = 100;
int y_size = 100;
int * buffer = malloc(sizeof(int)*x_size*y_size);
int ** array = malloc(sizeof(int *)*y_size);
for(int i = 0; i<y_size; i++)
array[i] = &buffer[i*x_size];
It looks like you might need some basic C tutorial.
int *buffer;
int **array;
int main()
{
int x_size=100;
int y_size=100;
int i;
/*int * */ buffer = malloc(sizeof(int)*x_size*y_size);
/*int ** */ array = malloc(sizeof(int*)*y_size);
for(i = 0; i<y_size; i++)
array[i]=&buffer[i*x_size];
array[0][1] = 5;
test();
return 0;
}
void test()
{
printf("%d",array[0][1]);
}

use a static variable (pointer) and allocate the array dynamically using malloc.

Related

LinkList not adding a new Node [duplicate]

I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.

Accessing a 2D array which is returned as a pointer in C

I'm trying to return a 2D array from a function. I've tried some ways mentioned in some websites. But they are helpless. So finally I'd assigned a pointer to the 2D array and returned it from the function. And the sample function's code is given below
float *test(int *x, int *y)
{
static float res[2][3];
float[] temp = {1,2,3};
for(int i=0;i<3;i++) res[0][i] = temp[i];
for(int i=0;i<3;i++) res[1][i] = temp[i]*-1;
float *ptr = &res[0][0];
return ptr;
}
Now I have a problem that how to access this 2D array in main function to print all of it's elements.
Could anyone give a solution? Thanks in advance:)
You have to go through dynamic allocation malloc is used for this.
Consider this code:
float **result = NULL; // if you want to return 2D array you need double pointer
result = (float **)malloc(2 * sizeof(float *)); // allocating assuming that the allocating will not fail otherwise it return NULL
for(int i = 0; i < 2; i++)
result[i] = (float *)malloc(3 * sizeof(float));
for(int i = 0; i < 3; i++) result[0][i] = i;
for(int i = 0; i < 3; i++) result[1][i] = i * -1;
return result;
Important part is also in main function where you should deallocate the memory to prevent memory leak. Is's done through free function and you should do this revere to the allocation to free all the memory you allocated.
for(int i=0;i<3;i++) free(result[i]); //done in main
free(result);
Declare the return type of your function properly, then just return the static array:
float (*test(int *x, int *y))[3]
{
static float res[2][3];
float temp[] = {1,2,3};
for(int i=0;i<3;i++) res[0][i] = temp[i];
for(int i=0;i<3;i++) res[1][i] = temp[i]*-1;
return res;
}
Note that returning a static array has the problem that all calls to the function will (re)use that same array, so the second call will clobber the array returned by the first call. You could instead malloc the array:
float (*test(int *x, int *y))[3]
{
float (*res)[3] = malloc(2 * sizeof *res);
float temp[] = {1,2,3};
for(int i=0;i<3;i++) res[0][i] = temp[i];
for(int i=0;i<3;i++) res[1][i] = temp[i]*-1;
return res;
}
but then the caller will need to remember to call free on the returned pointer when it is no longer needed.
You could return a pointer to static variable:
char (*modify(char input))[3]
{
static char variable[3][3];
variable[0][0] = input;
variable[1][1] = input+1;
return variable;
}
int main() {
char (*result)[3] = modify(a);
}
However, this is not a reentrant function. Another option is using dynamic memory (i.e. malloc), but memory leaks are quite common when returning pointers to allocated memory.
Another approach it's to pass the array to the function, already allocated, so you don't have to be worried about releasing memory or using statics:
void modify(char variable[][3], char input) {
variable[0][0] = input;
variable[1][1] = input+1;
}
int main(void) {
char result[3][3];
modify(result,a);
}
A better approach it's to create a typedef to highlight the purpose, length and making easier working with it:
typedef struct { char x[3][3]; } my2D_t;
void modify(my2D_t *variable, char input) {
variable->x[0][0] = input;
variable->x[1][1] = input+1;
}
int main() {
my2D_t result;
char a = 1;
modify(&result,a);
}
Also returning by value as tstanisl noticed. It creates another my2D_t, but the compiler will probably end up with something similar to the previous idea for the sake of optimization known as the "as-if" rule:
typedef struct { char x[3][3]; } my2D_t;
my2D_t modify(char input) {
my2D_t variable;
variable.x[0][0] = input;
variable.x[1][1] = input+1;
return variable;
}
int main() {
char a = 1;
my2D_t result = modify(a);
}

inicializing a structure with arrays of arrays [duplicate]

I'm trying to create a function that creates a variable sized 2D funct array. I'm using the following code, which seems to work just fine on its own:
typedef struct
{
//Starter Properties
int TypeB;
int TypeF;
int TypeW;
//Randomized Properties
int RandB;
int RandF;
int RandW;
//Derived Properties
int Speed;
} MapTileData;
MapTileData **Map;
int i, x=5, y=5;
//Allocate Initial Space
Map = (MapTileData**)calloc(x, sizeof(MapTileData));
for(i = 0; i < x; i++)
{
Map[i] = (MapTileData*)calloc(y, sizeof(MapTileData));
}
So the above code creates a 2D struct array. My attempts to move the code to a function have been less successful, giving segmentation faults when trying to print the array:
void CreateMap(MapTileData **Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
Map = (MapTileData**)calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = (MapTileData*)calloc(ySize, sizeof(MapTileData));
}
}
Used in the code:
MapTileData **MapTile;
CreateMap(MapTile,5,5);
Any and all help is greatly appreciated!
Function arguments are passed by value in C and modifying arguments in callee won't affect caller's local variables.
Use pointers to modify caller's local variables.
void CreateMap(MapTileData ***Map, int xSize, int ySize)
{
//Variables
int i;
//Allocate Initial Space
*Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
(*Map)[i] = calloc(ySize, sizeof(MapTileData));
}
}
Usage in the code:
MapTileData **MapTile;
CreateMap(&MapTile,5,5);
Alternate way: Pass the allocated array via the return value.
MapTileData **CreateMap(int xSize, int ySize)
{
//Variables
MapTileData **Map;
int i;
//Allocate Initial Space
Map = calloc(xSize, sizeof(MapTileData));
for(i = 0; i < xSize; i++)
{
Map[i] = calloc(ySize, sizeof(MapTileData));
}
//Return the value
return Map;
}
Usage in the code:
MapTileData **MapTile;
Maptile = CreateMap(5,5);
Also note that they say you shouldn't cast the result of malloc() and its family in C.

Unable to return array from another function to main function

I have been trying to pass my array address to print array values in main function. But it is not working as it gives "Count by X.exe has stopped working". It also shows a warning message which says "function is returning address of local variables". I am not able to find the problems. It would be helpful if anyone finds pointer related problem of my code which is given below.
#include<stdio.h>
int * countBy(int x, int n)
{
int arr[n];
int count = x;
for(int i = 0; i < n; i++)
{
arr[i] = count;
count = count + x;
}
return arr;
}
int main()
{
int x = 2, n = 10;
int * prr;
prr = countBy(x, n);
for(int i = 0; i < 10; i++)
{
printf("%d ", prr[i]);
}
return 0;
}
You cannot return arrays in C. You would either need to create the array in the main function and pass it to the function or use dynamic allocation.
Passing an output array:
void countBy(int x, int n, int *arr)
{
int count = x;
for(int i = 0; i < n; i++) {
arr[i] = count;
count = count + x;
}
}
int main(void)
{
int x = 2, n = 10;
int arr[n];
countBy(x, n, arr);
}
Dynamic allocation:
int * countBy(int x, int n)
{
int *arr = malloc(n * sizeof(*arr));
int count = x;
for(int i = 0; i < n; i++) {
arr[i] = count;
count = count + x;
}
return arr;
}
int main(void)
{
int x = 2, n = 10;
int *prr;
prr = countBy(x, n);
free(prr); // Remember to use free to not cause memory leaks
}
The local variables have a lifetime which extends only inside the block in which it is defined. The moment the control goes outside the block in which the local variable is defined, the storage for the variable is no more allocated (not guaranteed). Therefore, using the memory address of the variable outside the lifetime area of the variable will be undefined behaviour.
On the other hand you can do the following, replace the int arr[n] with a static array but the size of the array must be declared.
...
static int arr[10];
...
This will fix the problem but you couldnt change the size of the array if the user inputs the wanted size of it.

Can anyone explain me how to return a two dimensonal array in C from a function?

I am new to C and during my learning I want to return a two dimensional array from a function, so that I can use it in my main program. Can anyone explain me the same with example. Thanks in advance.
It depends how it is implemented. You can either work with just a one-dimensional array where you know the length of each (row) and the next row begins immediately after the previous one. OR, you can have an array of pointers to arrays. The extra cost though is you need to de-reference two pointers to get to one element of data.
// 2D array of data, with just one array
char* get_2d_ex1(int rows, int cols) {
int r, c, idx;
char* p = malloc(rows*cols);
for (r=0; r<rows; r++) {
for (c=0; c<cols; c++) {
idx = r*cols + c; // this is key
p[idx] = c; // put the col# in its place, for example.
}
}
return p;
}
Declare your function as returning a pointer to a pointer. If we use int as an example:
int **samplefunction() {
int** retval = new int*[100];
for (int i = 1; i < 100; i++) {
retval[i] = new int[100];
}
// do stuff here to retval[i][j]
return retval;
}
Here's an example of how you might create, manipulate and free a "2d array":
#include <stdlib.h>
#define ROWS 5
#define COLS 10
int **create_2d_array(size_t rows, size_t cols)
{
size_t i;
int **array = (int**)malloc(rows * sizeof(int*));
for (i = 0; i < rows; i++)
array[i] = (int*)malloc(cols * sizeof(int));
return array;
}
void free_2d_array(int **array, size_t rows, size_t cols)
{
size_t i;
for (i = 0; i < rows; i++)
free(array[i]);
free(array);
}
int main(void)
{
int **array2d = create_2d_array(ROWS, COLS);
/* ... */
array2d[3][4] = 5;
/* ... */
free_2d_array(array2d, ROWS, COLS);
return 0;
}
To create a "2d array"/matrix, all you have to do is create a dynamic array of pointers (in this case int*) of the size of the rows/width:
int **array = (int**)malloc(rows * sizeof(int*));
Then you set each of those pointers to point to a dynamic array of int of the size of the columns/height:
array[i] = (int*)malloc(cols * sizeof(int));
Note that the casts on malloc aren't required, it's just a habit I have.

Resources