I want my array to be global but i get my variables with scanf().
#include <stdio.h>
int m, n;
int main (void){
scanf("%d", &m);
scanf("%d", &n);
int array[m][n];
make_arr(array); //initializes array with random numbers
}
So what is the solution?
Edit: i use the solution of Farbod Shahinfar but i can't use it with my function:
void make_arr (int array[m][n] ){
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
What should i do?
You can declare a global pointer to an array and set it when you have scanned the input.
#include <stdio.h>
#include <stdlib.h>
int **array;
int m,n;
int main(void)
{
scanf("%d", &m);
scanf("%d", &n);
array = malloc(sizeof(int *) * m);
for (int i = 0; i < m; i++)
array[i] = malloc(sizeof(int) * n);
make_array(array);
// your other codes
// ....
for (int i = 0; i < m; i++)
free(array[i]);
free(array);
}
Memory allocated using malloc must be freed otherwise your program will have memory leakage problem.
Answer to the edit section:
You have declared a parameter for your make_arr function with the same name of the global variable this parameter will hide the global variable.
For clarification, if you declare a global variable you do not need to pass it as argument to a function.
void make_arr ()
{
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
// ....
}
Another approach is to pass the array to your function. This way you do not need the global variable at all. A possible function signature can be as below
void make_arr (int **array)
{
int i , j ;
srand(time(NULL));
for(i=0;i<m;i++)
for(j=0;j<n;j++)
array[i][j] = rand() % 2;
// ....
}
As Andrew Henle pointed out there is an awesome post on StackOverflow showing the right way of allocating multi-dimensional arrays. I have to confess that I did not knew about it.
Correctly allocating multi-dimensional arrays
Thanks to Andrew Henle for his constructive and useful comment
A note about malloc (Do read man page)
Malloc allocates memory from heap. You should check the man page of malloc for more information.
The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
First, given the variable-length array
int array[m][n];
your void make_arr( int array[m][n] ) won't work with int **array because int **array is not an actual 2-dimensional array. int **array is a pointer to an array of pointers to multiple and completely separate one-dimensional arrays. Such a construct is simply incompatible with being treated as an actual array.
And you can't give int array[m][n]; global scope because it's variable-length, and global variables are static (unchanging, not necessarily C's static) and have to be fixed-size.
And you can't use something like a typedef to create an "array type", because that's a compile-time definition and the array is "sized" at run time.
So you need to allocate the array dynamically, but the global variable use to access the array won't have sizing information associated with it.
The global variable pretty much has to be a void *.
To access the array, you have to create a pointer at run-time to a VLA and assign the global void * to that pointer.
This would work (note that the local pointer has to be dereferenced to access the array):
#include <stdlib.h>
void *array;
int m;
int n;
// create the array, assumes both
// m and n are already set
void createArray()
{
int ( *localArrayPtr )[m][n] = malloc( sizeof( *localArrayPtr ) );
array = localArrayPtr;
}
void fillArray( void )
{
int ( *localArrayPtr )[m][n] = array;
for ( int ii = 0; ii < m; ii++ )
{
for ( int jj = 0; jj < n; jj++ )
{
( *localArrayPtr )[ ii ][ jj ] = rand();
}
}
}
void someOtherFunc( void )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = ...;
}
As an exercise, it works. Forcing a VLA to have global scope, though, causes accessing the array to be more complex than necessary, adding to existing problems with using globally-scoped variables.
It's probably a lot better from both a scope and code complexity perspective to just pass the array to functions via arguments, such as void someFunc( int m, int n, int array[ m ][ n ] ) { ... }. Accessing elements would then just be in the form array[ x ][ y ].
You could create "getter" and "setter" functions to hide the complexity:
int getElement( int x, int y )
{
int ( *localArrayPtr )[m][n] = array;
return( ( *localArrayPtr )[ x ][ y ] );
}
void setElement( int x, int y, int value )
{
int ( *localArrayPtr )[m][n] = array;
( *localArrayPtr )[ x ][ y ] = value;
}
A good optimizing compiler would likely inline those.
As mentioned by Nate you can create a global pointer and then allocate memory to it using "malloc()"
#include<stdio.h>
#include<stdlib.h>
int *array;
int main() {
int m, n;
scanf("%d", &m);
scanf("%d", &n);
array = malloc(sizeOf(int) * m * n);
return 0;
}
And you can also ref this blog here:
Related
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 1 year ago.
#include<stdio.h>
#include <stdlib.h>
void deal_queries(int *arr, int limit, int numQueries, int filled) {
// Write your code here
for(int i=0;i<filled;i++)
{
printf("%d ",*(arr+0));
}
}
int * read_input(int N,int n){
//declare dynamic array of size N
// take input n integers and store them in the array and return pointer to this
int i;
int *ptr;
int array[N];
ptr=array;
for(i=0;i<n;i++)
{scanf("%d ",ptr);ptr++;}
ptr=array;
return (ptr);
}
int main()
{
int N,Q,n;
scanf("%d %d %d",&N,&Q,&n);
int* arr=read_input(N,n);
printf("%d ",*(arr+0));
deal_queries(arr,N,Q,n);
return 0;
}
when I print arr elements in main function I get correct values but if I pass them into deal with queries function I get random values can anyone explain why is this happening?
The variable array is local to read_input, so its life ends when returing from the function and accessing it after that is illegal.
Instead of that, you should allocate an array on the heap and use that.
#include<stdio.h>
#include <stdlib.h>
void deal_queries(int *arr, int limit, int numQueries, int filled) {
// Write your code here
for(int i=0;i<filled;i++)
{
printf("%d ",*(arr+0));
}
}
int * read_input(int N,int n){
//declare dynamic array of size N
// take input n integers and store them in the array and return pointer to this
int i;
int *ptr;
int *array=malloc(sizeof(*array)*N); /* allocate an array on the heap */
if(array==NULL) return NULL; /* check if allocation succeeded */
ptr=array;
for(i=0;i<n;i++)
{scanf("%d ",ptr);ptr++;}
ptr=array;
return (ptr);
}
int main()
{
int N,Q,n;
scanf("%d %d %d",&N,&Q,&n);
int* arr=read_input(N,n);
if(arr==NULL) return 1; /* check if allocation succeeded */
printf("%d ",*(arr+0));
deal_queries(arr,N,Q,n);
free(arr); /* free allocated array */
return 0;
}
You return the pointer to the local automatic storage variable which is UB as the variable stops existing when the function returns.
int array[N];
ptr=array;
for(i=0;i<n;i++)
{scanf("%d ",ptr);ptr++;}
ptr=array;
return (ptr);
You need to make it static (bad way) or dynamically allocate the memory
static int array[N];
ptr=array;
or better
//int array[N];
ptr=malloc(sizeof(*ptr)*N);
The error is in read_input where you have:
int array[N];
ptr=array;
return (ptr);
The variable array is a local variable in the function. And the assignment to ptr makes it point to the first element of this local array. This pointer will become invalid as soon as the function returns and the life-time of array ends.
You need to allocated the array dynamically using malloc instead:
int *array = malloc(N * sizeof *array);
int *ptr = array;
// Fill array using the ptr variable...
return array;
The pointer isn't a problem, it's what it points to. Here is the issue:
int * read_input(int N,int n) {
...
int array[N]; // This array is in automatic memory,
ptr=array; // so it is valid only inside read_input
...
return (ptr); // you are returning a pointer to it
}
In order to do what you want to do you need to use malloc:
int* ptr = malloc(sizeof(int)*N);
Use another pointer in the loop, or apply indexing to ptr, like this:
for (i = 0 ; i < n ; i++) {
scanf("%d ", &ptr[i]);
}
I don't know where I'm wrong and I get segmentation fault error. Can you help?
My Code;
#include <stdio.h>
#include <stdlib.h>
void do_array(int x, int y, int **arr){
arr=(int **)malloc(sizeof(int)*x);
for (int i=0;i<y;i++){
*(arr+i)=(int *)malloc(sizeof(int)*y);
}
}
int main(){
int **p;
do_array(5,2,p);
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
*(*(p+i)+j)=i;
}
}
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
printf("%d\n",*(*(p+i)+j));
}
}
return 0;
}
!!! I want to do is create a dynamic 2D array
The formal argument arr in the function is a separate object from the actual argument p in main - any changes to arr are not applied to p, so p is never set to point to the memory you just allocated.
What you will have to do is pass a pointer to p:
void doArr(int x, int y, int ***arr){
*arr=(int **)malloc(sizeof(int *)*x); // note type of sizeof - you're allocating an array of int *, not int
for (int i=0;i<y;i++){
*(*arr+i)=(int *)malloc(sizeof(int)*y);
}
}
...
doArr( 5, 2, &p );
Or, return arr and assign the result of doArr to p:
int **p = doArr( int x, int y )
{
int **arr = malloc(...);
...
return arr;
}
p = doArr( 5, 2 );
As Emanuel P notes, do is a keyword, so you can't use it as a function name.
A couple of style notes:
Since C89, malloc returns void * and does not require an explicit cast, and many of us will recommend against using it. It just adds visual noise and creates an extra maintenance burden.
Similarly, I often recommend that the operand of sizeof be your target expression, not a type name. Again, this eases your maintenance headaches if you change the type of the destination pointer.
Use array notation instead of pointer arithmetic where possible. It's easier to read and follow, and you're less likely to make a mistake.
Finally, always check the result of a malloc, calloc, or realloc call.
I'd rewrite your doArr function as follows:
void doArr(int x, int y, int ***arr)
{
*arr = malloc( sizeof **arr * x );
if ( *arr )
{
for ( int i = 0; i < y; i++ )
{
(*arr)[i] = malloc( sizeof *(*arr)[i] * y );
}
}
}
and call it as
doArr( 5, 2, &p );
int main(){
int **p /* = NULL */ ; // p is garbage or NULL
do_array(5,2,p); // p is still garbage or NULL
for (int i=0;i<5;i++){
for (int j=0;j<2;j++){
*(*(p+i)+j)=i; // p is still garbage or NULL
I want to do is create a dynamic 2D array
In your code you do not create a 2D array only the array of pointers.
void *doArr(size_t x, size_t y)
{
int (*arr)[x][y] = malloc( sizeof((*arr)[0][0]) * x * y);
return arr;
}
I allocate a non-square matrix in this way, but I'm not sure if I'm using the deallocation correctly
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m*sizeof(*arr));
for(i=0; i<m; i++)
{
arr[i]=malloc(n*sizeof(**arr));
}
return arr;
}
I have tried two way to free the memory
-Attempt A loop rows
void free_mem_mat(int m, float **array) {
int i;
for (i = 0; i < m; i++) {
free(array[i]);
}
free(array);
}
- Attempt B loop columns
void free_mem_mat(int n, float **array) {
int i;
for (i = 0; i < n; i++) {
free(array[i]);
}
free(array);
}
what should I use to free? the way A on the rows or the way B? (I know as written the method is the same I have rewritten this to be most clear possible)
You need one free() for each malloc()*. There were m+1 calls to malloc(); you'd better make m+1 calls to free() too.
Given that as the starting point, option A is the correct solution. However, it is also fair to note that the two functions (option A and option B) are strictly equivalent as long as you pass the m dimension given to the allocation function as the size argument of the deallocation function. The comment in option B is misleading; you're not looping over columns.
Given:
enum { MAT_ROWS = 20, MAT_COLS = 30 };
float **matrix = matrix_alloc(MAT_ROWS, MAT_COLS);
The correct call to free_mem_mat() is:
free_mem_mat(MAT_ROWS, matrix);
* This is an over-simplified statement if you use realloc() or calloc(). You need a free() for each malloc() that was not realloc()'d, and a free() for each realloc() that did not do a free() — by setting the size to 0. Treat calloc() as equivalent to malloc() as far as free() is concerned.
The trouble is that it has many allocations
I prefer this mode
#include <stdio.h>
#include <stdlib.h>
float **matrix_alloc(int m /* rows */, int n /* columns */)
{
int i;
float **arr = malloc(m * sizeof(float *));
*(arr) = malloc(m * n * sizeof(float));
for (i = 0; i < m; i++) {
*(arr + i) = (*(arr) + i * n);
}
return arr;
}
void free_mem_mat(float **array) {
free(*(array));
free(array);
}
int main () {
float **matrix = matrix_alloc(10, 20);
free_mem_mat(matrix);
return 0;
}
more information in:
http://c-faq.com/aryptr/dynmuldimary.html
arr was allocated as an array of m elements, each a pointer to some allocated memory. Therefore, you must free the m pointers in arr. In freeing each, you don't need to mention the size of the thing pointed to.
How to allocate dynamic memory for 2d array in function ?
I tried this way:
int main()
{
int m=4,n=3;
int** arr;
allocate_mem(&arr,n,m);
}
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*arr[i]=(int*)malloc(m*sizeof(int));
}
But it doesn't work.
Your code is wrong at *arr[i]=(int*)malloc(m*sizeof(int)); because the precedence of the [] operator is higher than the * deference operator: In the expression *arr[i], first arr[i] is evaluated then * is applied. What you need is the reverse (dereference arr, then apply []).
Use parentheses like this: (*arr)[i] to override operator precedence. Now, your code should look like this:
void allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n*sizeof(int*));
for(int i=0; i<n; i++)
(*arr)[i] = (int*)malloc(m*sizeof(int));
}
To understand further what happens in the above code, read this answer.
It is important that you always deallocate dynamically allocated memory explicitly once you are done working with it. To free the memory allocated by the above function, you should do this:
void deallocate_mem(int*** arr, int n){
for (int i = 0; i < n; i++)
free((*arr)[i]);
free(*arr);
}
Additionally, a better way to create a 2D array is to allocate contiguous memory with a single malloc() function call as below:
int* allocate_mem(int*** arr, int n, int m)
{
*arr = (int**)malloc(n * sizeof(int*));
int *arr_data = malloc( n * m * sizeof(int));
for(int i=0; i<n; i++)
(*arr)[i] = arr_data + i * m ;
return arr_data; //free point
}
To deallocate this memory:
void deallocate_mem(int*** arr, int* arr_data){
free(arr_data);
free(*arr);
}
Notice that in the second technique malloc is called only two times, and so in the deallocation code free is called only two times instead of calling it in a loop. So this technique should be better.
Consider this: Just single allocation
int** allocate2D(int m, int n)
{
int **a = (int **)malloc(m * sizeof(int *) + (m * n * sizeof(int)));
int *mem = (int *)(a + m);
for(int i = 0; i < m; i++)
{
a[i] = mem + (i * n);
}
return a;
}
To Free:
free(a);
If your array does not need to be resized (well, you can, but il will be a bit more complicated), there is an easier/more efficient way to build 2D arrays in C.
Take a look at http://c-faq.com/aryptr/dynmuldimary.html.
The second method (for the array called array2) is quite simple, less painful (try to add the tests for mallocs' return value), and way more efficient.
I've just benchmarked it, for a 200x100 array, allocated and deallocated 100000 times:
Method 1 : 1.8s
Method 2 : 47ms
And the data in the array will be more contiguous, which may speed things up (you may get some more efficient techniques to copy, reset... an array allocated this way).
Rather allocating the memory in many different block, one can allocate this in a consecutive block of memory.
Do the following:
int** my2DAllocation(int rows,int columns)
{
int i;
int header= rows *sizeof(int *);
int data=rows*cols*sizeof(int);
int ** rowptr=(int **)malloc(header+data);
if(rowptr==NULL)
{
return NULL:
}
int * buf=(int*)(rowptr+rows);
for(i=0;i<rows;i++)
{
rowptr[i]=buf+i*cols;
}
return rowptr;
}
That is an unnecessarily complicated way of allocating space for an array. Consider this idiom:
int main(void) {
size_t m = 4, n = 3;
int (*array)[m];
array = malloc(n * sizeof *array);
free(array);
}
I have tried the following code for allocating memory to 2 dimensional array.
#include<stdio.h>
#include<malloc.h>
void main(void)
{
int **p;//double pointer holding a 2d array
int i,j;
for(i=0;i<3;i++)
{
p=(int**)(malloc(sizeof(int*)));//memory allocation for double pointer
for(j=(3*i+1);j<(3*i+4);j++)
{
*p = (int*)(malloc(sizeof(int)));//memory allocation for pointer holding integer array
**p = j;
printf(" %d",**p);//print integers in a row
printf("\n");
p++;
}
}
}
Output of the above code is:-
1 2 3
4 5 6
7 8 9
In order to understand 2 dimensional array in terms of pointers, we need to understand how it will be allocated in memory, it should be something like this:-
1 2 3
1000 --> 100 104 108
4 5 6
1004 --> 200 204 208
7 8 9
1008 --> 300 304 308
from the above, we understand that, when we allocate memory to pointer p which is a double pointer, it is pointing to an array of integers, so in this example, we see that the 0x1000 is pointer p.
This pointer is pointing to integer pointer *p which is array of integers, when memory is allocated inside the inner for loop, during first iteration the pointer is 0x100 which is pointing to integer value 1, when we assign **p = j. Similarly it will be pointing to 2 and 3 in the next iterations in the loop.
Before the next iteration of the outer loop, double pointer is incremented, inside the next iteration, as is seen in this example the pointer is now at 0x1004 and is pointing to integer pointer which is an array of integers 4,5,6 and similarly for the next iterations in the loop.
Try the following code:
void allocate_mem(int*** arr,int n, int m)
{
*arr=(int**)malloc(n*sizeof(int*));
for(int i=0;i<n;i++)
*(arr+i)=(int*)malloc(m*sizeof(int));
}
2d Array dynamically array using malloc:
int row = 4;
int column = 4;
int val = 2;
// memory allocation using malloc
int **arrM = (int**)malloc (row*sizeof(int*));
for (int i=0;i<row;i++)
{
arrM[i] = (int*)malloc(column*sizeof(int));
// insert the value for each field
for (int j =0;j<column;j++,val++)
{
arrM[i][j] = val;
}
}
// De-allocation
for (int i=0;i<row;i++)
{
free(arrM[i]);
}
free(arrM);
arrM = 0;
//
// Now using New operator:
//
int **arr = new int*[row];
int k = 1;
for (int i=0;i<row;i++)
{
arr[i] = new int[column];
// insert the value for each field
for (int j =0;j<column;j++,k++)
{
arr[i][j] = k;
}
}
cout<<"array value is = "<<*(*(arr+0)+0)<<endl;
cout<<"array value is = "<<*(*(arr+3)+2)<<endl;
// Need to deallcate memory;
for (int i=0;i<row;i++)
{
delete [] arr[i];
}
delete []arr;
arr = 0;
I'm writing a method that receives a number l and returns a vector of size l with random numbers. I have this code, but does not work
#include <time.h>
int makea (int z) {
int a1[z];
int i;
for (i = 0; i < tam; i++) {
a1[i]=srand(time(0));
}
return a1;
}
These are the errors that the compiler returns me
arrays1.c: In function 'makea':
arrays1.c:12: error: void value not ignored as it ought to be
arrays1.c:14: warning: return makes integer from pointer without a cast
arrays1.c:14: warning: function returns address of local variable
I think is a problem of pointers... but I'm not really sure
A few problems:
Your array is allocated on the stack, meaning that when your function exits, the memory you return will be invalid
In C, you cannot return an array from a function, it must first decay into a pointer.
So, to fix, use malloc and a pointer:
int *makea (int z) {
int *a1 = malloc(sizeof(int) * z);
int i;
srand(time(NULL));
for (i = 0; i < tam; i++) {
a1[i]= rand();
}
// remember to free a1 when you are done!
return a1;
}
Also note that using malloc can sometimes basically grant you the 'random number' scenario for free, negating the need to loop through the elements as the value returned from malloc is garbage (and thus random numbers).
However, also note that malloc is implementation-specific, meaning that an implementation could theoretically clear the memory for you before returning it.
Your best bet is:
Declare the array outside of the routine, and pass it in to initialize it:
void init_array (int a[], nelms)
Plan B is pass a pointer to a pointer, and have the routine allocate and initialize it
Like this:
void alloc_and_init_array (int **a_pp, int nelms)
{
*a_pp = malloc (sizeof (int) * nelms);
...
... or, equivalently ...
int *
alloc_and_init_array (int nelms)
{
int *a_p = malloc (sizeof (int) * nelms);
...
return a_p;
A local variable like your array is allocated on the stack. At function return it is removed from the stack, so the pointer you return points to an unallocated memory location.
You have to allocate the array with malloc() or pass an already existing array to the function.
#include <time.h>
int makea (int z) {
int *a1 = (int*)malloc(z*sizeof(int));
int i;
for (i = 0; i < tam; i++) {
a1[i]=srand(time(0));
}
return a1;
}
IMPORTANT: remember to free memory allocated somewhere outside, when you do not need it anymore.
Well, first off your function says that it returns an int, yet you want to return an array, so that is wrong. Of course, you can't return an array in C either...
Second, you will have to return a pointer. You cannot copy arrays via assignment or assign a new value to an array at all in C, so your function won't be very useful. Either return an int* or take an int** as an output argument and initialize it in your function.
Also, your array is locally allocated, so even if the compiler didn't complain you would be returning invalid memory.
int makea (int size, int **out_array) {
int *temp, i;
if(!out_array)
return 0;
temp = malloc(sizeof(int) * size);
if(!temp)
return 0;
srand(time(0));
for (i = 0; i < size; ++i)
temp[i] = rand();
*out_array = temp;
return 1;
}
int main() {
int *arr;
if(!makea(10, &arr)) {
printf("Failed to allocate array");
return -1;
}
return 0
}
Another note:
temp[i] = srand(time(0));
That is wrong. srand seeds the random number generator, but does not return a random number. You call srand to input the seed and then call rand to get a random number.