I'm calling a function which returns a 3D array. The problem is that if I declare the array inside the function it returns a dangling pointer as the execution of the program goes out of the scope of the variable. But when I declare the array outside the function, it gives Error:'array' was not declared in this scope. How should I declare the array? It returns integer type.
int arr[x][y][z];
int func(list of parameters)
{
//code
return arr;
}
int main()
{
int arr2[x][y][z];
arr2 = func(list of parameters);
return 0;
}
You try to return an integer value with a name arr, but you did not define int arr in the function scope.
C does not allow to return array by value. You need to pass a pointer to an array to the function in order to let it to modify array.
Something like:
void func(int*** array, <list of parameters>)
{
//code
array[1][2][4] = 10;
}
int main()
{
int arr2[x][y][z];
func(arr2, <list of parameters>);
return 0;
}
few problems in your code:
First, func function should return an int*** pointer. it is defined as returning int which is not the type you actually return.
Second, why retuning the global arr array from func? it simply modifies the global array.
int arr[x][y][z];
int func(list of parameters)
{
//code
return arr;
}
Third, why declaring arr2 to hold the result - simply reference the global array you've defined.
Fourth, defining int arr[x][y][z]; globally is not supported - the compiler would not know how to create this buffer - you should declare it with actual size to the array (e.g., int arr[10][10][10];
Either pass the array as a parameter in the function if you are declaring it outside the function or if you are declaring it inside the function then to deal with a dangling pointer
is for example -
char*func()
{
char str[10];
strcpy(str,"Hello!");
return(str);
}
//returned pointer points to str which has gone out of scope.
or you might be using memory that is being freed for example
int *c = malloc(sizeof(int));
free(c);
*c = 3; //writing to freed location!
Related
What option is recommended in C to return an array from a function?
Option 1:
void function_a(int *return_array){
return_array[0] = 1;
return_array[1] = 0;
}
Option 2:
int* function_b(){
int return_array[2];
return_array[0] = 1;
return_array[1] = 0;
return return_array;
}
This function
int* function_b(){
int return_array[2];
return_array[0] = 1;
return_array[1] = 0;
return return_array;
}
returns a pointer to the first element of a local array with automatic storage duration that will not be alive after exiting the function.
So the returned pointer will be invalid and dereferencing such a pointer invokes undefined behavior.
You could return a pointer to first element of an array from a function if the array is allocated dynamically or has static storage duration that is when it is declared with the storage class specifier static.
As for the first function then it will be more safer if you will pass also the number of elements in the array like
void function_a(int *return_array, size_t n );
and within the function you will be able to check the passed value.
I'd most prefer:
void function_a(int return_array[const], size_t sz) {
return_array[0] = 1;
return_array[1] = 0;
}
Because it clearly indicates that the parameter is an Array, and it also clearly indicates the size of the array that is passed in, making out-of-bounds indicies less likely to be a problem.
So, I am just trying to wrap my head around "pointer function that returns a pointer to an array"... but to start off slowly, I had to understand this:
void Print(const char c){
printf("\nPrint: %c\n", c);
}
int main () {
void (*FunctionPointer)(const char);
FunctionPointer = &Print;
FunctionPointer('a');
}
Which I do - pretty easy to guess what is going on... FunctionPointer just points to the location where the Print function "resides". Instead of jumping to a specific memory address (stored on a register) of a specific function, I can now be more flexible and point to any function that I want to access.
But I am stuck with the following...
int main () {
int (*FunctionPointer())[];
}
Now it seems that the function that is pointed by FunctionPointer, can in fact return a pointer to an array of type int. The compiler accepts the second line - so far so good - and I also understand the concept... but I am getting stuck regarding the implementation.
FunctionPointer needs - once again, to point to a function. That function can indeed return a pointer that points to an array of type int... soooooo:
int *Array(){
int ar[2] = {5,6};
return ar;
}
int main () {
int (*FunctionPointer())[];
FunctionPointer = &Array;
}
However, the last piece of code is just not accepted by the compiler.... So, what gives?
With
int (*FunctionPointer())[];
you've declared FunctionPointer as a function returning a pointer to an array of int -- not a function pointer. You want
int *(*FunctionPointer)();
If you use [] here, you'll get an error, as functions can't return arrays -- arrays are not first class types -- and unlike with function parameters, arrays will not be silently converted to pointers when used as the return value of a function type. With that, you'll still get the warning
t.c:3:12: warning: function returns address of local variable [-Wreturn-local-addr]
return ar;
^~
which is pretty self-explanatory
You have declared the array of function pointers. Arrays can't be assignable. Functions can't return arrays. You might wish
int* (*FunctionPointer)();
FunctionPointer = &Array;
Function pointers are much easier when you use typedefs. You can simply use the same notation as "normal" data pointers.
// func is a function type. It has one parater and returns pointer to int
typedef int *func(const char);
// funcptr is a pointer to func
func *funcptr;
I want a function to return a pointer to an array of size 10. What is the prototype for such a function?
I have tried 3 different prototypes and it doesn't work:
int(*)[10] returnPtrArray(int (*arr)[10])
{
return arr;
}
//The return type doesn't seem to work
int(*)[10] returnPtrArray(int[][10]);
int (returnPtrArray(int[][10])(*)[10];
int(*)(returnPtrArray(int[][10])[10];
//none of these prototypes seem to work
//calling
int main()
{
int a[5][10];
int (*ptr)[10] = returnPtrArray(&a);
//How do I make this work?
}
The correct definition of the function would be:
int (*returnPtrArray(int (*arr)[10]))[10]
{
return arr;
}
Breaking this down: returnPtrArray is a function:
returnPtrArray()
That takes a pointer to an array of 10 int:
returnPtrArray(int (*arr)[10])
And returns a pointer:
*returnPtrArray(int (*arr)[10])
To an array of size 10:
(*returnPtrArray(int (*arr)[10]))[10]
Of int:
int (*returnPtrArray(int (*arr)[10]))[10]
And you would call it like this:
int a[5][10];
int (*ptr)[10] = returnPtrArray(a);
Try this prototype:
int (*returnPtrArray(int (*arr)[10]))[10];
which is method named returnPtrArray, and takes as a parameter a pointer to an array of 10 integers.
It returns a pointer to an array of 10 integers.
Check it out in the Live demo, where I removed the & from the parameter in the method call, since it would be wrong.
This answer was based on the more analytic post Declare a C/C++ function returning pointer to array of integer pointers.
Pointers don't have knowledge of what they point to, beyond type. If you need to pass an array, you need to pass in a pointer along with the length of the array in a separate parameter (or use a list implementation like std::vector).
I am storing my information in an array of pointers to structs. In other words, each element of the array is a pointer to a linked list.
I don't know how long the array should be, so instead of initializing the array in my main() function, I instead intialize the double pointer
struct graph** graph_array;
Then once I obtain the length of the array, I try to initialize each element of graph_array using a function GraphInitialize:
int GraphInitialize(struct graph* *graph_array,int vertices)
{
struct graph* graph_array2[vertices+1];
graph_array = graph_array2;
int i;
for (i=0;i<vertices+1;i++)
{
graph_array[i] = NULL;
}
return 0;
}
But for some reason this is not returning the updated graph_array to main(). Basically, this function is updating graph_array locally, and no change is being made. As a result, any time I try to access an element of graph_array it seg faults because it is not initialized. What am I doing wrong?
Edit: Following the convo with Tom Ahh I should add something else that makes this more confusing.
I don't call GraphIntialize directly from main(). Instead, I call getdata() from main, and pass a pointer to graph_array to getdata as shown below.
getdata(argc, argv, vertpt, edgept, &graph_array)
int getdata(int argc, char *argv[], int *verts, int *edges, struct graph* **graph_array)
Then getdata gets the number of vertices from my input file, and uses that to call GraphInitialize:
if ((GraphInitialize(&graph_array, *verts)) == -1)
{
printf("GraphCreate failed");
return 0;
}
This results in an error: "expected 'struct graph 3ASTERISKS' but argument is of type 'struct graph 4ASTERISKS'.
When you assign something to graph_array, you simply assign it to its local copy. The changes made to it in the function will not be see-able by the caller. You need to pass it by pointer value to be able to change its value. Change your function prototype to int GraphInitialize(struct graph ***graph_array,int vertices) and when you call it, use GraphInitialize(&graph_array, 42).
Second problem in your code is when you create graph_array2, you declare it to be local to your GraphInitialize() function. Thus, when exiting your function, graph_array2 is destroyed, even if you assigned it to *graph_array. (the star dereferences the pointer to assign it to the value it points to).
change your assignation to *graph_array = malloc(sizeof(*graph_array) * vertices); and you should be fine.
Memory is divided into two parts, the stack and the heap. Malloc will give you back a chunk of memory from the heap, which lives on between functions, but must be freed. Thus your program must be careful to keep track of the malloced() memory and call free() on it.
Declaring a variable graph_array2[vertices+1] allocates a local variable on the stack. When the function returns the stack pointer is popped "freeing" the memory allocated in the function call. You don't have to manage the memory manually, but when the function call is over it no longer exists.
See here for some discussion of the two allocation styles:
http://www.ucosoft.com/stack-vs-heap.html
You're using C99-style local array allocation. The array disappears when the function returns. Instead you need to use malloc() to allocate memory that will persist after the function. You can use typedefs to make your code more readable:
typedef struct graph_node_s { // linked list nodes
struct graph_node_s *next;
...
} GRAPH_NODE;
typedef GRAPH_NODE *NODE_REF; // reference to node
typedef NODE_REF *GRAPH; // var length array of reference to node
GRAPH AllocateGraph(int n_vertices)
{
int i;
GRAPH g;
g = malloc(n_vertices * sizeof(NODE_REF));
if (!g)
return NULL;
for (i = 0; i < n_vertices; i++)
g[i] = NULL;
return g;
}
You have two problems.
First, graph_array2 has auto extent, meaning that it only exists within its enclosing scope, which is the body of the GraphInitialize function; once the function exits, that memory is released, and graph_array is no longer pointing anywhere meaningful.
Second, any changes to the parameter graph_array are local to the function; the changes won't be reflected in the caller. Remember, all parameters are passed by value; if you pass a pointer to a function, and you want the value of the pointer to be modified by the function, you must pass a pointer to the pointer, like so:
void foo(int **p)
{
*p = some_new_pointer_value();
return;
}
int main(void)
{
int *ptr = NULL;
foo(&ptr);
...
}
If you intend for InitializeGraph to allocate the memory for your array, you'll need to do something like this:
int InitializeGraph(struct graph ***graph_array, int vertices)
{
*graph_array = malloc(sizeof **graph_array * vertices);
if (*graph_array)
{
int i;
for (i = 0; i < vertices; i++)
{
(*graph_array}[i] = NULL; // parentheses matter here!
}
}
else
{
return -1;
}
return 0;
}
int main(void)
{
int v;
struct graph **arr;
...
if (GraphInitialize(&arr, v) == 0)
{
// array has been allocated and initialized.
}
...
}
Postfix operators like [] have higher precedence than unary operators like *, so the expression *arr[i] is interpreted as *(arr[i]); we're dereferencing the i'th element of the array. In GraphInitialize, we need to dereference graph_array before subscripting (graph_array isn't an array, it points to an array), so we need to write (*graph_array)[i].
I've just started to work with C, and never had to deal with pointers in previous languages I used, so I was wondering what method is better if just modifying a string.
pointerstring vs normal.
Also if you want to provide more information about when to use pointers that would be great. I was shocked when I found out that the function "normal" would even modify the string passed, and update in the main function without a return value.
#include <stdio.h>
void pointerstring(char *s);
void normal(char s[]);
int main() {
char string[20];
pointerstring(string);
printf("\nPointer: %s\n",string);
normal(string);
printf("Normal: %s\n",string);
}
void pointerstring(char *s) {
sprintf(s,"Hello");
}
void normal(char s[]) {
sprintf(s,"World");
}
Output:
Pointer: Hello
Normal: World
In a function declaration, char [] and char * are equivalent. Function parameters with outer-level array type are transformed to the equivalent pointer type; this affects calling code and the function body itself.
Because of this, it's better to use the char * syntax as otherwise you could be confused and attempt e.g. to take the sizeof of an outer-level fixed-length array type parameter:
void foo(char s[10]) {
printf("%z\n", sizeof(s)); // prints 4 (or 8), not 10
}
When you pass a parameter declared as a pointer to a function (and the pointer parameter is not declared const), you are explicitly giving the function permission to modify the object or array the pointer points to.
One of the problems in C is that arrays are second-class citizens. In almost all useful circumstances, among them when passing them to a function, arrays decay to pointers (thereby losing their size information).
Therefore, it makes no difference whether you take an array as T* arg or T arg[] — the latter is a mere synonym for the former. Both are pointers to the first character of the string variable defined in main(), so both have access to the original data and can modify it.
Note: C always passes arguments per copy. This is also true in this case. However, when you pass a pointer (or an array decaying to a pointer), what is copied is the address, so that the object referred to is accessible through two different copies of its address.
With pointer Vs Without pointer
1) We can directly pass a local variable reference(address) to the new function to process and update the values, instead of sending the values to the function and returning the values from the function.
With pointers
...
int a = 10;
func(&a);
...
void func(int *x);
{
//do something with the value *x(10)
*x = 5;
}
Without pointers
...
int a = 10;
a = func(a);
...
int func(int x);
{
//do something with the value x(10)
x = 5;
return x;
}
2) Global or static variable has life time scope and local variable has scope only to a function. If we want to create a user defined scope variable means pointer is requried. That means if we want to create a variable which should have scope in some n number of functions means, create a dynamic memory for that variable in first function and pass it to all the function, finally free the memory in nth function.
3) If we want to keep member function also in sturucture along with member variables then we can go for function pointers.
struct data;
struct data
{
int no1, no2, ans;
void (*pfAdd)(struct data*);
void (*pfSub)(struct data*);
void (*pfMul)(struct data*);
void (*pfDiv)(struct data*);
};
void add(struct data* x)
{
x.ans = x.no1, x.no2;
}
...
struct data a;
a.no1 = 10;
a.no1 = 5;
a.pfAdd = add;
...
a.pfAdd(&a);
printf("Addition is %d\n", a.ans);
...
4) Consider a structure data which size s is very big. If we want to send a variable of this structure to another function better to send as reference. Because this will reduce the activation record(in stack) size created for the new function.
With Pointers - It will requires only 4bytes (in 32 bit m/c) or 8 bytes (in 64 bit m/c) in activation record(in stack) of function func
...
struct data a;
func(&a);
...
Without Pointers - It will requires s bytes in activation record(in stack) of function func. Conside the s is sizeof(struct data) which is very big value.
...
struct data a;
func(a);
...
5) We can change a value of a constant variable with pointers.
...
const int a = 10;
int *p = NULL;
p = (int *)&a;
*p = 5;
printf("%d", a); //This will print 5
...
in addition to the other answers, my comment about "string"-manipulating functions (string = zero terminated char array): always return the string parameter as a return value.
So you can use the function procedural or functional, like in printf("Dear %s, ", normal(buf));