Apologies if this is a "basic" question, but I am new to C and can't find the answer. My question is regarding the need to malloc a variable and return its pointer within a function, compared with creating the variable within the function and returning the result.
The first issue that comes to mind is that any variables declared within the scope of the function will be destroyed once the function terminates; so why is it then that the following is valid:
int add(int a, int b)
{
int result;
result = a + b;
return result;
}
But the following is not?
char *concat(char* a, char* b)
{
char result[10];
strcat(result, a);
strcat(result, b);
return result;
}
The warning you get is that you are returning an address to a local variable, but this is what we are also doing in the first function? Does the behaviour differ depending on the type?
For a more real example, I'm very confused regarding which of the following 2 functions I should be using, as they both work perfectly well for my program:
struct Card *card_create(enum Rank rank, enum Suit suit)
{
struct Card *card = malloc(sizeof(struct Card));
if(card == NULL) {
fprintf(stderr, "malloc: %s", strerror(errno));
return NULL;
}
card->rank = rank;
card->suit = suit;
return card;
}
Or:
struct Card card_create(enum Rank rank, enum Suit suit)
{
struct Card card;
card.rank = rank;
card.suit = suit;
return card;
}
Again, sorry if this is a nooby question, but I'd really appreciate an explanation. Thanks!
In your add() function, you return the value that is held (until the function exits) in its local variable result. The storage for that variable is no longer available once the function returns, but the value that was stored there is just a number, not in itself dependent on that storage.
In your concat() function, the expression result evaluates to a pointer to the local storage for an array of 10 char. You can still return the pointer's value, but once the function exits the meaning of that value is no longer defined.
So, no, the behavior of returning a value does not itself differ between those cases, but the usefulness -- indeed the risk -- associated with doing so varies greatly.
Does the behaviour differ depending on the type?
Kind of. When you return something in C, you return the value, not a pointer to the value or anything that depends on any variables still existing. However, there's an unrelated rule that says that in almost all contexts, a value of array type is implicitly converted to a pointer to the array's first element. Thus, the second code snippet is returning a pointer into the array, while the first snippet just returns an int.
Very interesting question
When a function return local variable as vlue, A new variable will be created and stored in CPU registers( depends on compiler). After that, local variable will be freed.
int add(int a, int b)
{
int result;
result = a + b;
return result; // 1. A new int variable will be created and stored in CPU registers (depends on Compiler)
// 2. result will be freed at the end of function
}
In CPP, the process is very similar to C, card constructor will be called twice
struct Card card_create(enum Rank rank, enum Suit suit)
{
struct Card card;
card.rank = rank;
card.suit = suit;
return card; // 1. New Card object will be created and stored in CPU register(Depends on compiler)
// 2. card will be freed at the end of function
}
Hope this help.
In the first code snip, the value of an int variable is being returned. Very OK.
In the second code snip, the address of a local (stack) variable is being returned. Not OK.
And, perhaps the line:
char[10] result;
would be better as:
char result[10];
If the second example declared result as follows:
char result;
then the value in result could be returned:
return(result);
However, the second example defines result as an array of char; making result a pointer to the beginning of this array. Hence, the true value of result in the second example is an address to local stack memory (which disappears when the function scope terminates).
The first example captures the value of result (an integer value) and sends the value back to the caller, (not the address of the value in the function's local scope).
Related
Is the following code (func1()) correct if it has to return i? I remember reading somewhere that there is a problem when returning a reference to a local variable. How is it different from func2()?
int& func1()
{
int i;
i = 1;
return i;
}
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
This code snippet:
int& func1()
{
int i;
i = 1;
return i;
}
will not work because you're returning an alias (a reference) to an object with a lifetime limited to the scope of the function call. That means once func1() returns, int i dies, making the reference returned from the function worthless because it now refers to an object that doesn't exist.
int main()
{
int& p = func1();
/* p is garbage */
}
The second version does work because the variable is allocated on the free store, which is not bound to the lifetime of the function call. However, you are responsible for deleteing the allocated int.
int* func2()
{
int* p;
p = new int;
*p = 1;
return p;
}
int main()
{
int* p = func2();
/* pointee still exists */
delete p; // get rid of it
}
Typically you would wrap the pointer in some RAII class and/or a factory function so you don't have to delete it yourself.
In either case, you can just return the value itself (although I realize the example you provided was probably contrived):
int func3()
{
return 1;
}
int main()
{
int v = func3();
// do whatever you want with the returned value
}
Note that it's perfectly fine to return big objects the same way func3() returns primitive values because just about every compiler nowadays implements some form of return value optimization:
class big_object
{
public:
big_object(/* constructor arguments */);
~big_object();
big_object(const big_object& rhs);
big_object& operator=(const big_object& rhs);
/* public methods */
private:
/* data members */
};
big_object func4()
{
return big_object(/* constructor arguments */);
}
int main()
{
// no copy is actually made, if your compiler supports RVO
big_object o = func4();
}
Interestingly, binding a temporary to a const reference is perfectly legal C++.
int main()
{
// This works! The returned temporary will last as long as the reference exists
const big_object& o = func4();
// This does *not* work! It's not legal C++ because reference is not const.
// big_object& o = func4();
}
A local variable is memory on the stack, and that memory is not automatically invalidated when you go out of scope. From a function deeper nested (higher on the stack in memory), it’s perfectly safe to access this memory.
Once the function returns and ends though, things get dangerous.
Usually the memory is not deleted or overwritten when you return, meaning the memory at that address is still containing your data - the pointer seems valid.
Until another function builds up the stack and overwrites it.
This is why this can work for a while - and then suddenly cease to function after one particularly deeply nested set of functions, or a function with really huge sized or many local objects, reaches that stack-memory again.
It even can happen that you reach the same program part again, and overwrite your old local function variable with the new function variable. All this is very dangerous and should be heavily discouraged.
Do not use pointers to local objects!
A good thing to remember are these simple rules, and they apply to both parameters and return types...
Value - makes a copy of the item in question.
Pointer - refers to the address of the item in question.
Reference - is literally the item in question.
There is a time and place for each, so make sure you get to know them. Local variables, as you've shown here, are just that, limited to the time they are locally alive in the function scope. In your example having a return type of int* and returning &i would have been equally incorrect. You would be better off in that case doing this...
void func1(int& oValue)
{
oValue = 1;
}
Doing so would directly change the value of your passed in parameter. Whereas this code...
void func1(int oValue)
{
oValue = 1;
}
would not. It would just change the value of oValue local to the function call. The reason for this is because you'd actually be changing just a "local" copy of oValue, and not oValue itself.
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));
I know why this works:
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
*number = p;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
What I don't understand is why this doesn't (in my machine it prints 3700 or something like that).
#include <stdio.h>
void cool_number(int **number) {
int value = 42;
int *p = &value;
int **x = &p;
number = x;
}
int main () {
int *number;
cool_number(&number);
printf("number is %d\n", *number);
return 0;
}
Why aren't both equivalent?
both are evil as they capture the address of a stack variable.
Second one doesn't do what you expect because you are assigning directly to the parameter number, which is only temporary, the first one changes something the parameter number pointers to, which is the same thing as number in main points to.
I assume they're not equivalent because number is passed by value, on the stack, as is standard for function parameters. Any changes that you make directly to number inside of cool_number() are modifying the local copy on the stack, and are not reflected in the value of number in main().
You get around this in the first example by dereferencing number, which tells the computer to modify some specific location in memory that you also happen to have a pointer to back in main(). You don't have this in the second example, so all that happens is that you make the local number pointer point to somewhere else, without actually updating any memory location being referred to back in main(). Thus nothing you do shows up once you get back to main().
And since value is local to the cool_number() function, setting a reference to it that will be accessed after cool_number() returns isn't guaranteed to work and certainly shouldn't be used in any code outside of a trivial/toy example. But in this specific instance it's not really related to why you're seeing different results between the two pieces of code.
As I understand, in both cases, your code is wrong.
In the first case, you are returning an address to a variable allocated on stack, which will be deallocated as soon as the function returns.
In the second case, the error of the first case exists, plus you are passing number by value, so an updation to number will not get reflected in the caller function.
In 'C', arguments are always passed by value. So, you cannot update the argument passed as it is. For Ex:
int func(int a)
{
a = 5; // In this case the value 5 will not be reflected in the caller as what is updated is the local copy of a on the stack
}
int func(int *a)
{
*a = 5; // This update will show in caller as you are directly updating the memory pointed to by a
a = malloc(4); //This update will not show in caller as again you are updating the local copy of stack
}
#include <stdio.h>
void cool_number(int **number) {
int value = 42; /* this "value" hold 42 value,
and it lifetime is only in this function */
int *p = &value; /* here we get the address of "value" in memory */
*number = p;
}
int main () {
int *number;
cool_number(&number); /* after this function the "value" in memory had been recyled
and may be used by other program */
printf("number is %d\n", *number); /* so when we print value here it will be
a unpredictable value, somehow may be crash */
return 0;
}
both the same principle
Title pretty much sums this up. How come it's possible that i can assign a locally created Point a (in the function ReadPoint()) into a variable that's in a different scope. Doesn't the locally created Point a gets 'popped' away along with stack of function readPoint() ? What exactly is going on ?
struct Point readPoint(void)
{
struct Point a;
printf("x = ");
scanf("%lf",&b.x);
printf("y = ");
scanf("%lf",&b.y);
return a;
}
int main(int argc, char **argv) {
Point test = readPoint();
printPoint(test);
return 0
}
structs are no different to primitive types in this regard. It's exactly the same principle as:
int foo(void)
{
int x = 5;
return x;
}
int main(void)
{
int y = foo();
printf("%d\n", y);
}
The details of how this is achieved are implementation-dependent. But usually, the return value (whether it's an int or a struct) is placed onto the stack by the called function, and then the caller then can then access that stack location.
The struct is "copied", byte by byte, into test in main...just like returning an int from a function and assigning it to a variable.
This, however, wouldn't happen if you were returning a pointer to the struct and the dereferencing it and assigning (or something similar).
When returning, you'll create a copy of the object (with all members of the struct), but the local variable/object is still destroyed.
This will work unless you try to return a reference or pointer (in these cases your compiler should warn you about this stupid idea). This will work fine, unless you're trying to create a copy of something working with pointers.
In C++ this would include references too.
This is because on return from readPoint() all structure values are copied to another locally defined structure test. Structure a does not survive.
What you're seeing is structure assignment. Almost all modern compilers can handle this.
This is a very simple question but what does the following function prototype mean?
int square( int y, size_t* x )
what dose the size_t* mean? I know size_t is a data type (int >=0). But how do I read the * attached to it? Is it a pointer to the memory location for x? In general I'm having trouble with this stuff, and if anybody could provide a handy reference, I'd appreciate it.
Thanks everybody. I understand what a pointer is, but I guess I have a hard hard time understanding the relationship between pointers and functions. When I see a function prototype defined as int sq(int x, int y), then it is perfectly clear to me what is going on. However, when I see something like int sq( int x, int* y), then I cannot--for the life of me--understand what the second parameter really means. On some level I understand it means "passing a pointer" but I don't understand things well enough to manipulate it on my own.
How about a tutorial on understanding pointers?
In this case however, the pointer is probably used to modify/return the value. In C, there are two basic mechanisms in which a function can return a value (please forgive the dumb example):
It can return the value directly:
float square_root( float x )
{
if ( x >= 0 )
return sqrt( x );
return 0;
}
Or it can return by a pointer:
int square_root( float x, float* result )
{
if ( x >= 0 )
{
*result = sqrt( result );
return 1;
}
return 0;
}
The first one is called:
float a = square_root( 12.0 );
... while the latter:
float b;
square_root( 12.00, &b );
Note that the latter example will also allow you to check whether the value returned was real -- this mechanism is widely used in C libraries, where the return value of a function usually denotes success (or the lack of it) while the values themselves are returned via parameters.
Hence with the latter you could write:
float sqresult;
if ( !square_root( myvar, &sqresult ) )
{
// signal error
}
else
{
// value is good, continue using sqresult!
}
*x means that x is a pointer to a memory location of type size_t.
You can set the location with x = &y;
or set the value were x points to with: *x = 0;
If you need further information take a look at: Pointers
The prototype means that the function takes one integer arg and one arg which is a pointer to a size_t type. size_t is a type defined in a header file, usually to be an unsigned int, but the reason for not just using "unsigned int* x" is to give compiler writers flexibility to use something else.
A pointer is a value that holds a memory address. If I write
int x = 42;
then the compiler will allocate 4 bytes in memory and remember the location any time I use x. If I want to pass that location explicitly, I can create a pointer and assign to it the address of x:
int* ptr = &x;
Now I can pass around ptr to functions that expect a int* for an argument, and I can use ptr by dereferencing:
cout << *ptr + 1;
will print out 43.
There are a number of reasons you might want to use pointers instead of values. 1) you avoid copy-constructing structs and classes when you pass to a function 2) you can have more than one handle to a variable 3) it is the only way to manipulate variables on the heap 4) you can use them to pass results out of a function by writing to the location pointed to by an arg
Pointer Basics
Pointers And Memory
In response to your last comment, I'll try and explain.
You know that variables hold a value, and the type of the variable tells you what kind of values it can hold. So an int type variable can hold an integer number that falls within a certain range. If I declare a function like:
int sq(int x);
...then that means that the sq function needs you to supply a value which is an integer number, and it will return a value that is also an integer number.
If a variable is declared with a pointer type, it means that the value of that variable itself is "the location of another variable". So an int * type variable can hold as its value, "the location of another variable, and that other variable has int type". Then we can extend that to functions:
int sqp(int * x);
That means that the sqp function needs to you to supply a value which is itself the location of an int type variable. That means I could call it like so:
int p;
int q;
p = sqp(&q);
(&q just means "give me the location of q, not its value"). Within sqp, I could use that pointer like this:
int sqp(int * x)
{
*x = 10;
return 20;
}
(*x means "act on the variable at the location given by x, not x itself").
size_t *x means you are passing a pointer to a size_t 'instance'.
There are a couple of reasons you want to pass a pointer.
So that the function can modify the caller's variable. C uses pass-by-value so that modifying a parameter inside a function does not modify the original variable.
For performance reasons. If a parameter is a structure, pass-by-value means you have to copy the struct. If the struct is big enough this could cause a performance hit.
There's a further interpretation given this is a parameter to a function.
When you use pointers (something*) in a function's argument and you pass a variable you are not passing a value, you are passing a reference (a "pointer") to a value. Any changes made to the variable inside the function are done to the variable to which it refers, i.e. the variable outside the function.
You still have to pass the correct type - there are two ways to do this; either use a pointer in the calling routine or use the & (addressof) operator.
I've just written this quickly to demonstrate:
#include <stdio.h>
void add(int one, int* two)
{
*two += one;
}
int main()
{
int x = 5;
int y = 7;
add(x,&y);
printf("%d %d\n", x, y);
return 0;
}
This is how things like scanf work.
int square( int y, size_t* x );
This declares a function that takes two arguments - an integer, and a pointer to unsigned (probably large) integer, and returns an integer.
size_t is unsigned integer type (usually a typedef) returned by sizeof() operator.
* (star) signals pointer type (e.g. int* ptr; makes ptr to be pointer to integer) when used in declarations (and casts), or dereference of a pointer when used at lvalue or rvalue (*ptr = 10; assigns ten to memory pointed to by ptr). It's just our luck that the same symbol is used for multiplication (Pascal, for example, uses ^ for pointers).
At the point of function declaration the names of the parameters (x and y here) don't really matter. You can define your function with different parameter names in the .c file. The caller of the function is only interested in the types and number of function parameters, and the return type.
When you define the function, the parameters now name local variables, whose values are assigned by the caller.
Pointer function parameters are used when passing objects by reference or as output parameters where you pass in a pointer to location where the function stores output value.
C is beautiful and simple language :)
U said that u know what int sq(int x, int y) is.It means we are passing two variables x,y as aguements to the function sq.Say sq function is called from main() function as in
main()
{
/*some code*/
x=sr(a,b);
/*some other code*/
}
int sq(int x,int y)
{
/*code*/
}
any operations done on x,y in sq function does not effect the values a,b
while in
main()
{
/*some code*/
x=sq(a,&b);
/*some other code*/
}
int sq(int x,int* y)
{
/*code*/
}
the operations done on y will modify the value of b,because we are referring to b
so, if you want to modify original values, use pointers.
If you want to use those values, then no need of using pointers.
most of the explanation above is quite well explained. I would like to add the application point of view of this kind of argument passing.
1) when a function has to return more than one value it cannot be done by using more than one return type(trivial, and we all know that).In order to achieve that passing pointers to the function as arguments will provide a way to reflect the changes made inside the function being called(eg:sqrt) in the calling function(eg:main)
Eg: silly but gives you a scenario
//a function is used to get two random numbers into x,y in the main function
int main()
{
int x,y;
generate_rand(&x,&y);
//now x,y contain random values generated by the function
}
void generate_rand(int *x,int *y)
{
*x=rand()%100;
*y=rand()%100;
}
2)when passing an object(a class' object or a structure etc) is a costly process (i.e if the size is too huge then memory n other constraints etc)
eg: instead of passing a structure to a function as an argument, the pointer could be handy as the pointer can be used to access the structure but also saves memory as you are not storing the structure in the temporary location(or stack)
just a couple of examples.. hope it helps..
2 years on and still no answer accepted? Alright, I'll try and explain it...
Let's take the two functions you've mentioned in your question:
int sq_A(int x, int y)
You know this - it's a function called sq_A which takes two int parameters. Easy.
int sq_B(int x, int* y)
This is a function called sq_B which takes two parameters:
Parameter 1 is an int
Parameter 2 is a pointer. This is a pointer that points to an int
So, when we call sq_B(), we need to pass a pointer as the second
parameter. We can't just pass any pointer though - it must be a pointer to an int type.
For example:
int sq_B(int x, int* y) {
/* do something with x and y and return a value */
}
int main() {
int t = 6;
int u = 24;
int result;
result = sq_B(t, &u);
return 0;
}
In main(), variable u is an int. To obtain a pointer to u, we
use the & operator - &u. This means "address of u", and is a
pointer.
Because u is an int, &u is a pointer to an int (or int *), which is the type specified by parameter 2 of sq_B().
Any questions?