Pointer giving random values after passing into function [duplicate] - c

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]);
}

Related

Value of an array does not change in call by address

In this program new value will be added to the array at end. When the memory is reallocated why it is not reflected back to the actual parameter
#include<stdio.h>
void insertion(int* arr,int *n)
{
int val,n1=*n;
int *temp;
printf("\nEnter element to append");
scanf("%d",&val);
temp=malloc(sizeof(int)*n1);
for(i=0;i<n1;i++)
{
temp[i]=arr[i];
}
n2=n1+1;
arr=malloc(sizeof(int)*n2);
for(i=0;i<n1;i++)
{
arr[i]=temp[i];
}
arr[n1]=val;
*n=n2;
}
int main()
{
int n=4;
int arr[4]={1,2,3,4},i;
insertion(arr,&n);
for(i=0;i<n;i++)
{
printf("\t%d",arr[i]);
}
}
There are two reasons for this.
First, you're assigning the return value of malloc to arr, which is a parameter to the function and therefore local. This means that changing the value of arr isn't reflected in the calling function.
Even if you fixed this, you would have a problem because arr in main is an actual array allocated locally, so you can't change its size.
You would first need to change arr in main to be a pointer and to allocate space for it with malloc so that you can use realloc later, and you need to change insertion to take a int ** so that the actual pointer value in main can be changed.
Because the parameter is passed by value.
You change arr in insertion, there's no reason that should change arr in main. They're different variables. This is how C works.
But in main arr is an array, which means it couldn't be changed even if you got the code right.
Here's how to do it right, if you want to change something in main you have to return the vaue from your function.
#include<stdio.h>
int* insertion(int* arr,int *n)
{
...
return arr; // return the new value of arr
}
int main()
{
int n=4;
int* arr = malloc(n*sizeof(int)); // arr is a pointer, not an array
for (int i = 0; i < n; ++i)
arr[i] = i+1;
arr=insertion(arr,&n); // get the returned value from insertion
for(i=0;i<n;i++)
{
printf("\t%d",arr[i]);
}
}

How can i use an variable-length array globally?

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:

Realloc changes the values of the array but array still has the same address in C Programming [duplicate]

This question already has answers here:
Dynamic memory access only works inside function
(1 answer)
How do I modify a pointer that has been passed into a function in C?
(7 answers)
Closed 2 years ago.
I have a question regarding dynamic allocation.
Why do the array values change after using realloc? It works fine if the initial size of the array is greater than the next size (e.g. 10 20) but if the initial size of the array is lesser than the next size (e.g. 20 10), the code gives me garbage values.
The code works properly in local side but when I try it on online compilers, it does not work the way it's supposed to.
Is there anything wrong with my code? Or is it a problem with online compilers? And am I using the realloc function properly?
#include<stdio.h>
#include<stdlib.h>
void print(int *ptr, int size);
void reallocate(int *ptr, int size);
void assign(int *ptr, int size);
int main(void) {
int n;
// Set initial size for array
scanf("%d",&n);
int *arr = (int*) malloc(n * sizeof(int));
// Assign values from 0 to n-1
assign(arr, n);
// Print values assigned
print(arr, n);
printf("\n");
// Set new size for reallocation
scanf("%d",&n);
reallocate(arr, n);
// Assign values again
assign(arr, n);
// Print values
print(arr,n);
return 0;
}
// Prints values of the array
void print(int *ptr, int size) {
for(int i = 0; i < size; i++) printf("%d ",ptr[i]);
}
// Reallocates new size for array
void reallocate(int *ptr, int size) {
ptr = realloc(ptr, size*sizeof(int));
}
// Assigns values from 0 to n-1
void assign(int *ptr, int size) {
for(int i = 0; i < size; i++) ptr[i] = i;
}
I hope for your responses.

Trouble with using calloc with an array and returning a pointer

As a reference this is the second part of my assignment:
int* generateFibonacci(int size);
This function will take as input an integer called size. The value contained in the size variable
will represent how many numbers in the Fibonacci sequence to put into the array. The function
will use calloc to create the array of this size and then fill the array with size numbers from the
Fibonacci sequence, starting with 1 and 1. When the array is complete the function will return a
pointer to it.
My trouble come in play when I get the error in line 8 "warning: assignment makes and integer from pointer without a cast".
Another error I get is in line 19 "warning: return makes pointer from integer without a cast".
So my question is, how am I suppose to set up calloc to make the array with a size from a user, then return a pointer to it?
#include <stdio.h>
#include <stdlib.h>
int* generateFibonacci(int size)
{
int i, array[size];
array[size]=(int*)calloc(size, sizeof(int));
array[0]=0;
array[1]=1;
for(i = 2; i < size+1; i++)
array[i] = array[i-2] + array[i-1];
return *array;
}
void printHistogram (int array[], int size)
{
int i, j;
for(i=0; i <= size; ++i)
{
for(j=0; j < array[i]; j++)
{
printf("*");
}
printf("\n");
}
}
int main(void)
{
int array[100], size;
printf("how big will your Fibionacci number be? ");
scanf("%i", &size);
generateFibonacci(size);
printHistogram(array, size);
return 0;
}
how am I suppose to set up calloc to make the array with a size from a user, then return a pointer to it?
For a 1D array of int * Use printf() and scanf()
int *array = {0}; //Note, leaving this initialization method for posterity
//(See related comments below.)
//however agreeing with commentator that the more idiomatic
//way to initialize would be: int *array = NULL;
size_t size = 0;
printf("Enter order of array");
scanf("%d", &size);
array = malloc(size);//create memory with space for "size" elements
if(array){//do other stuff}
But it is unclear from your example, and the comment if you really intend using a 2D array....
As stated in the comments, You have created an int array, then attempted to create memory for it.
int i, array[size];
...
array[size]=(int*)calloc(size, sizeof(int));//wrong
As it is created, array does not need memory. Memory is created on the stack as automatic.
If you wanted a 2D array of int. Then you could do it like this:
int *array[size]; //create a pointer to int []
With this, you can create an array of arrays (in concept) in this way:
for(i=0;i<size;i++) array[i]= calloc(size, sizeof(int));//do not cast the output, not necessary
Now, you essentially have a size x size 2D array of int. It can be assigned values in this manner:
for(i=0;i<size;i++)
for(j=0;j<size;j++)
array[i][j]=i*j;//or some more useful assignment
By the way, adjust the parameters of the calloc() statement as needed, but note, casting its output is not necessary.
Regarding the return statement, your function is prototyped to return a int *.
int* generateFibonacci(int size){...} //requires a return of int *
If you decide to use a 1D array, i.e. int *array={0} (requiring that you allocate memory), then return:
return array;//array is already a `int *`, just return it.
If you are using the 2D array, then to return a int *, you must decide which of the size elements of the array you want to return:
return array[i];//where `i` can be any index value, from 0 to size-1

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