In the Wikipedia article https://en.wikipedia.org/wiki/Pure_function#Impure_functions it says that the following function is not pure.
int f(int* x)
{
return *x;
}
Why is that? The function would return the same value for the same argument right? Would it be considered pure if it was a non-mutable reference, as in the following?
int f2(const int* x)
{
return *x;
}
f isn't pure because its return value isn't necessary the same for the same arguments. You could call f twice with the same inputs and get different outputs. The following program demonstrates this:
#include <stdio.h>
int main() {
int i = 3;
int * const x = &i;
printf("%d\n", f(x));
i = 4;
printf("%d\n", f(x));
return 0;
}
Because x doesn't change between the two calls, the second call to f(x) could be optimized away (in favour of reusing the result from the first call) if f was pure. Obviously, that could produce the wrong result, so f isn't pure.
f2 isn't pure for the same reason.
Rule 1 says:
Its return value is the same for the same arguments (no variation with local static variables, non-local variables, mutable reference arguments or input streams from I/O devices).
The point is that the argument is not the value pointed by x but rather the address of the pointer. You're passing an address to the function.
Since you can change the pointed data and pass the same address then you have different return values.
Of course this wouldn't be true if f or f2 returned int* instead that int. In that case the same argument would lead to the same return value.
Related
Is there any problem with using another function call as a function parameter in C?
int foo1(int a){/*does something */ return a;}
int foo2(int b){/*does something */ return b;}
int foo3(int a, int b){return a+b;}
int result = foo3(foo1(1),foo2(2)); /*result is 3 */
To expand on tstanisl's comment
int foo1(int a) { puts("ONE"); return a++; }
int foo2(int b) { puts("TWO"); return b++; }
int foo3(int a, int b) { return a+b; }
int result = foo3(foo1(1),foo2(2));
There is no specific order for the prints. Any of
ONE TWO
TWO ONE
is possible. Can even change next time you recompile (or run) your executable!
There's no problem with the code in your question.
That code looks very much like it's intended to demonstrate a potential problem with calls like foo3(foo1(1),foo2(2)), but it fails to do so.
For example:
int foo1(int a){return a++;}
The expression a++ has a side effect, but one that's irrelevant. The parameter a is a local variable, and it ceases to exist when the function returns. It might as well be just return a; (except for possible undefined behavior if the increment overflows).
This:
int n = 42;
int func(int param) { return param++; }
returns the value 42 and does not affect the value of n. The ++ applies to a copy of n, not to n itself. Function arguments in C are passed by value.
The potential problem with that kind of call is that the order of the evaluation of the arguments is unspecified. The calls foo1(1) and foo2(2) have no side effects that are visible to the caller, but a call like foo3(a++, a++) would, and could yield different results depending on the unspecified order in which the arguments are evaluated. (I'm not 100% certain whether that case has undefined behavior; it depends on whether there's a sequence point between the evaluations of the arguments. But that uncertainty alone is more than enough reason to avoid writing code like that.)
I work on my tutorial in C language.
I have a small pice of code that I need to deciph.
Here is the code:
int f(){return 1;}
int g(){return 2;}
int (*h(int (*pf1)(), int (*pf2)()))(){
return (int (*) ())((pf1() > pf2())*(int)pf1 + (pf2()>pf1())*(int)pf2);
}
void main(){
int res = h(f,g)();
}
I have problem to unndestand this syntex:
int (*h(int (*pf1)(), int (*pf2)()))()
I can't understand what is the meaning of this outter parentheses ->(*h(int (*pf1)(), int (*pf2)()))
and this parentheses() at the end of the function's signature.
Also what is '*h' inside parentheses? I understand that it get two functions and trigger it.
Can I get brif explanation on questions above?
Function pointers can be tricky to read. I start by reading the inner-most parenthesis, and work my way to the outer-most parenthesis.
Here's a breakdown of that declaration:
int (*h(int (*pf1)(), int (*pf2)()))()
(*pf1)() and (*pf2)() are pointers to functions that accept no parameters (i.e. ()), and both of them return an int.
*h(int (*pf1)() , int (*pf2)()) is a function that accepts two function pointers that returnint s. So, h returns a pointer to a function that accepts nothing and returns an int
Here is a link to some examples of the syntax, and a more elaborate breakdown:
https://www.cprogramming.com/tutorial/function-pointers.html
Added:
Since the original code that was provided segfaults, I wrote two different implementations that compare two integers and return the bigger one.
First, look at j. It's just a regular function that accepts two parameters that happen to be function pointers. Those function pointers are then used within the function. And because we said j returns an int, we return the actual integer by calling pf1() or pf2() with ().
Now look at h. In this scenario, h is going to return a pointer *. So we still call the function pointers pf1() and pf2() in h, but when we return, we DO NOT use () because we want to return the whole function pointer (either pf1 or pf2).
Lastly, look at main and see the difference between how j and h are used. Again, j is just a regular function. However, h uses the this syntax: h(f,g)() because h returns a pointer to a function which we then want to call using () to get the actual integer result for printing.
Hope this helps provide a little more clarity with a working example! Good luck!
#include <stdio.h>
int f(){return 1;}
int g(){return 2;}
int j(int (*pf1)(), int (*pf2)())
{
return ((pf1() > pf2() ? pf1() : pf2()));
}
int (* h( int(*pf1)() , int(*pf2)() ) ) ()
{
return (pf1() > pf2() ? pf1 : pf2);
}
int main()
{
int res1 = j(f,g);
int res2 = h(f,g)();
//print values returned by calling f and g.
printf("f: %d \ng: %d\n", f(),g());
//print result of calling j(f,g)
printf("res1: %d\n", res1);
//print result of calling h(f,g)()
printf("res2: %d\n", res2);
return 0;
}
main calls the function returned by h and returns that result. h compares the output of f and g and returns the function which returns the larger value (else it returns 0). Since the output of g is greater than f, h returns g. Hence main returns 2.
#include <stdio.h>
#include <stdlib.h>
int f(int x) {
return x;
}
int main ( int argc,char * argv[]) {
int a=4;
f(a);
printf("PASSED!\n");
return 0;
}
What happens when you call f(a) without assigning it to anything?
What happens when you call a function with return value without assigning it to any variable?
The return value of a function need not be used or assigned. It is ignored (usually quietly).
The function still executes and its side effects still occur.
Consider the 3 functions: int scanf(), int f(), and int printf(), their return values are all ignored yet the functions were still executed.
int a=4;
scanf("%d", &a);
f(a);
printf("PASSED!\n");
It is not good to ignore return values in robust code, especially scanf().
As commented by #Olaf, a warning may be enabled by some compilers.
Explicit ignoring the result of a function is sometime denoted with (void) to quiet that warning.
(void) f(a);
Using your example, we can look at how it evaluates line by line. Starting in main.
int a=4;
We now have a variable a with the value 4.
f(a);
So now the function f is called with a, which has a value of 4. So in the function f, the first parameter is named x and it just returns that parameter x.
So the evaluation of
f(a);
is just
4;
And a program like this compiles and runs perfectly fine.
int main(int argv, char *argv[]) {
1 + 1;
return 0;
}
What happens when you call f(a) without assigning it to anything?
--> Nothing at all.
What happens when you call a function (which has return value) without assigning it to anything?
-->The function will be executed, either make no sense like your case or make a lot of senses like modifying a static variable or a global variable. The return value will be ignored.
The return value will normally be stored in a register and will not fade.
It will be overwritten when the register is needed by the compiler.
If the function is inline it may be detected by the compiler that the value isn't used and ignore the value from being computed at all.
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed 7 years ago.
I do not understand the concept of pass by value in C. Here is my function:
void add(int x){
x = x+1;
}
and when I call the function:
int y=3;
add(y);
but when I compile, I still get 3. I've been told it has something to do with pass-by-value but I still do not understand? Can anyone explain why?
Pass by value creates a copy of the argument. It is this copy that is changed in the function
void add(int x){
x = x+1;
}
Thus the change you make is made to the copy and not the variable in your main scope (that you are expecting to see changed).
If you want to change a variable within a function by passing it as a parameter you cannot pass by value. You could change your function to pass by pointer like this
void add(int* x){
*x = *x + 1;
}
and pass the address of an integer to the function like this
int y=3;
add(&y);
within main()
The pointer is still passed by value so it is a copy of the pointer that is being acted on, but this doesn't matter as you are not changing the pointer itself, you are changing the value of the variable it points to.
This function:
void add(int x) {
x = x + 1;
}
Essentially says this: create a function named add, that returns nothing (void), and takes a single integer argument x. Then you call the function:
y = 3;
add(y);
This says "Set the variable named y to 3. Now call the add() function passing as an argument the current value of y, namely 3. This is no different from
add(3);
The argument x is entirely local to the function add(). It exists only inside the function, and does not affect anything outside it.
So your function dutifully adds 1 to the number you gave it, and then throws it away. Just like you told it to.
C has no "pass by reference" like other languages, where you can tell a function to act on a variable itself rather than its current value. It does, however, have pointers, which can accomplish similar things.
All function arguments in C are passed by value. That means that the parameter (in this case, x defined in add) is initialized to a copy of the value of the argument (in this case, y, which has the value 3).
Since x is a local variable, executing
x = x + 1;
changes the value of x, but that change has no effect after the function returns and x no longer exists.
Note that the argument doesn't have to be the name of a variable. You can legally call your function like this:
add(42);
x is initialized to 42 -- but x = x + 1 certainly isn't going to change the value of 42.
If you want to modify the value, you can have the function return the new value:
int add(int x) {
return x + 1;
}
The caller can do anything it likes with the result, including assigning it back to the variable:
int y = 3;
y = add(y);
Or you can pass the address of the object you want to modify:
int add(int *x) {
*x = *x + 1;
}
and then the caller can do this:
int y = 3;
add(&y);
This is still pass-by-value, but the value being passed is a pointer value, the address of x. It's how we can emulate pass-by-reference in C.
You can solve above by using the code :
int add(int x)
{ x=x+1;
return x;}
then use
a new variable like
k= add(y);
and then print k.
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?