I'm trying to understand the behavior of pointers in C in context of passing them as arguments to function, so I tried messing around and making the following test case:
void function1(int argument)
{
argument=4;
}
and
void function2(int* argument)
{
*argument=5;
}
if I run the following statements:
int var1;
int* var2;
function1(var1);
function1(*var2);
function2(&var1);
function2(var2);
In which cases will changes made to the variables be reflected in the calling function?
I tried running the following sample code but am not able to understand output
#include <stdio.h>
void funone(int arg)
{
arg=5;
}
void funtwo(int* arg)
{
*arg=6;
}
int main(void) {
int var1=0;
int *var2;
var2=(int *)malloc(sizeof(int));
*var2=0;
funone(var1);
printf("%d",var1);
funone(*var2);
printf("%d",*var2);
funtwo(&var1);
printf("%d",var1);
funtwo(var2);
printf("%d",*var2);
return 0;
}
the output I'm getting is
0066
what is the implication of this output?
Your code for function1 changes the value of the variable in the function only. So there are no repercussions of the change outside of the function.
Your function2 works (ie, changes the values it points to) because pointers can point to variables outside of it's scope. But your first function keeps the value inside of it's scope, and once the function returns any changes are lost.
This explanation should be present in any good tutorial about pointers.
Neither of those examples will work as you're simply setting the value of the pointer using those functions. Below you will find a version which achieves the behaviour you wish:
void function2(int* argument)
{
*argument=5;
}
The reason for the asterisk before the argument parameter is because you are dereferencing the value of the pointer (you are getting access to it) and therefore you may, at that point change its value...
I hope this helps...
Related
I need to figure out how to use a void type function to change a value in another function, so I'm trying to write a practice program that uses a procedure to change an integer from 5 to 4 and then prints the new integer (should be 4).
#include <stdio.h>
#include <stdlib.h>
void change(int x)
{
x = 4;
}
int main(int argc, char **argv)
{
int z = 5;
change(z);
printf("%d\n",z);
return 0;
}
This prints 5 at the end. I can tell there's some kind of issue with scope here, but I can't figure out how to resolve it. I also can't print within the procedure, so that solution is out of the question. I'd really appreciate any help!
To change a variable within another function, that isn't in the scope of the function, you must pass the variable by pointer.
void change(int *x)
{
*x = 4;
}
And call the function using change(&z).
If the variable isn't passed by pointer, then only the variable inside the scope of the function will change, but not its argument.
In C, function arguments are always passed by value. This means that any changes made to a value in a function are not reflected in the caller. That is what's happening in your case.
Fortunately, you can pass a pointer (by value of course) instead. This allows you, via dereferencing, to change the value that the pointer is pointing to.
To do this, adjust the prototype of your function to
void change(int* x)
Then, within that function, use
*x = 4;
And, finally, call the function using
change(&z);
You need to pass the address of the variable and then you can change the value of the variable.
void change(int *x)
{
*x = 4;
}
Now the invoking function will have new value of x which is 4.
You can pass a pointer to the function, like so:
void change(int *x)
I'm trying to use a separate function to input data using scanf() (outside of main). This new function is supposed to print a line and then receive input from the user. However something appears to be going awry between the scanf in the function and the printf() function in the main that I am testing it with.
I believe that I am receiving a pointer from the function but certain compiler warning are making me wonder if my assumption about the pointer is even correct.
I am confused by the output of this code:
#include <stdio.h>
void set_Info(void);
int main()
{
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
return 0;
}
void set_Info(void) /* start of function definition */
{
int scanNum;
printf("Scan test, enter a number");
scanf("%d",&scanNum);
}
If I provide a number, say 2, the result of the printf statement in the main() is:
2665560
Now, in so far as I am able to tell that output appears to me like a memory address so what i attempted to do to fix that is dereference the pointer in main like so :
int scanNum = 0;
int scanNumHolder;
set_Info();
scanNumHolder = *scanNum;
printf("%d", &scanNumHolder);
I believe that this code makes scanNum variable to become assigned to the dereferenced value of scanNum. However I get the same output as above when I do this. Which leads me to believe one of two things. Either that I am not correctly dereferencing scanNum, or that scanNum is not in fact a pointer at all in this situation.
The most common error I receive from the compiler is:
error: invalid type argument of unary β*β (have βintβ)
Which makes sense, I suppose, if I'm attempting to treat an int value as a pointer.
If it is the case that scanNum is not being dereferenced correctly, how can I achieve this?
Thank you for the help
*Update
Thanks for the help.
Just to recap
My set_info function needs to be passed an address parameter. The reason an address parameter has to be used is because the local memory of a function is erased after the function call ends. So in order to do work a variable declared in the main function, I pass the address of the variable in question so that when the function ends the changes are not lost.
Inside the main function, when set_info is called with &scanNum as the argument, it passes a reference tp the variable so that it can be assigned the value generated by the scanf statement in the function.
I realize that what I was doing wrong as correctly pointed out by the awesome people of SO, is that I am trying to call set_info like it returns a value but in fact changes the variable like I actually want.
Thanks again for the help!
This function:
void set_Info(void)
{
int scanNum;
scanf("%d", &scanNum);
}
reads the integral number from the standard input and stores it into scanNum variable, which is local variable with automatic storage duration that exists only within the scope of this function.
And the body of your main:
int scanNum = 0;
set_Info();
printf("%d", &scanNum);
defines a local variable called scanNum, then calls a set_Info() function which doesn't affect scanNum defined in main in any way and then it prints the address of scanNum variable.
This is what you are trying to do:
void set_Info(int* num)
{
// read an integer and store it into int that num points to:
scanf("%d", num);
}
int main()
{
int scanNum = 0;
// pass the address of scanNum to set_Info function so that
// changes to scanNum are visible in the body of main as well:
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
I also recommend you spend more time reading some book with C basics before you'll continue programming :)
I would pass in the variable into your set_Info function, so that it knows where to save the data. This would then allow you to scan multiple values, and you would simple increment the pointer. Be sure to pass the variable address into set_Info() using &variableName, since that function expects a pointer
#include <stdio.h>
void set_Info(int *pScanNum);
int main()
{
int scanNum = 0;
set_Info(&scanNum);
printf("%d", scanNum);
return 0;
}
//Pass in the pointer to scanNum
void set_Info(int *pScanNum)
{
printf("Scan test, enter a number");
scanf("%d",pScanNum);
}
Get rid of your ampersand! Printf wants an integer not a pointer.
printf("%d", scanNum);
And as liho said, you need to return scanNum from set_info so you can get at it outside of the function.
int scanNum = set_Info();
This should be a simple question, but I might not be able to word it correctly or I might be trying to defy the principles of the C language because of my lack of experience with it.
All I want to do is, given a pointer to a function, to wrap it inside another function that takes a pointer to a function as an argument, and make a pointer of the later. Better in code:
void do_nothing_1() {}
void do_nothing_2() {}
void wrapper(void(*f)()) { f(); }
int main() {
// the following will call the function
// but i just want a pointer of whats being called
funcion_pointer_1 = wrapper(do_nothing_1);
funcion_pointer_2 = wrapper(do_nothing_2);
return 0;
}
I apologize beforehand if the question doesn't make any sense, please help me clarify it rather than simply downvote it.
Edit: Given the apparent difficulty to obtain the results desired because of the obscurity of the requirements, I will be a little more specific on what I am looking for.
Inside a struct, I have a pointer to a function:
struct my_struct {
int (* run)(void);
}
What I want to do is to modify that function and that's why I use the wrapper. So, for example, if foo returns void change that to int. Also, run some code before executing foo:
int wrapper(void (*foo)()) {
// exec some stuff here
foo();
return 0;
}
Ultimately, what I want is that when I execute the function corresponding to the *run pointer from my structure, execute some stuff before doing run() and change the return type.
When struggling with the correct syntax, it is helpful to use typedefs to make things clearer. Not just for yourself as you write the code, but for anyone who needs to maintain it, or just try to figure out what it's doing.
You want a function pointer to a function that takes another function pointer as an argument. Start with the argument, a function without parameters and no return value:
typedef void (*void_handler_t)( void);
And now the wrapper function pointer, one that takes a function pointer parameter and has no return value:
typedef void (*wrapper_handler_t)( void_handler void_fn);
And the code:
void foo( void) {}
void wrapper( void_handler_t wrapped_fn)
{
wrapped_fn();
}
int main( int argc, char *argv[])
{
wrapper_handler_t function_pointer;
function_pointer = &wrapper;
function_pointer( &foo);
return 0;
}
all. I'm currently working with an old established code base for a new project which is basically undocumented (i.e. averages 1 one-line comment per file). I just ran into something which I haven't seen before and am not quite sure how to interpret.
Firstly, they define a function type and a function in the header file (.h) in the form:
typedef void (*SOME_FUNCTION)(void *data, EXECUTION_CONTEXT *ec);
void add_function(SOME_FUNCTION aFunction, void *data);
In the main source file (.c), there is a function defined:
void add_function(void (*f)(void *data), void *data)
{
(Some code here)
}
So okay, there's a function pointer... but what the heck happened to the second argument, ec? Why would someone use a code design like this? For reference, when the function add_function is used, it is used in this sort of form:
void passedFunction(void *data, EXECUTION_CONTEXT *ec)
{
(Stuff the function does.)
}
void CallingFunction()
{
data = (some data stuff);
add_function((SOME_FUNCTION)passedFunction, data);
}
So, as you can see, the passed functions use the correct form that fits the original SOME_FUNCTION argument signature, but the definition for the add_function arguments is short by one argument.
Formally, the results are undefined: you are only permitted to call a function via a function pointer if the types match.
As for what actually happens, it depends on the calling convention and what the function does with the arguments. Chances are, the results aren't going to be good.
To add on James' answer:
Since the default calling convention is most likely cdecl, the call site is responsible for cleaning up the stack after passedFunction returns. Since the call site knows that it passed just 1 argument to the callee, the compiler can clean up the stack normally (even though technically this is undefined behavior).
Change the calling convention on passedFunction to stdcall though, and you 're in for some fireworks.
From the example code below, it doesn't appear that the variable(s) that are defined in the function pointer matters during the check. The code below compiles without warning.
#include <stdio.h>
int temp(int (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(int (*m)()) {
return 1;
}
However, the code below throws an error.
#include <stdio.h>
int temp(void (*m)());
int main(int argc, char *argv[]) {
return temp(main);
}
int temp(void (*m)()) {
return 1;
}
Due to this; it seems that the compiler (at least in my case GCC) only cares what the return value of the function pointer will be. The interesting thing here is that you CAN send the parameters correctly but if you do NOT specify the parameter (in our example m()), then the variables in m() when called will be junk.
I need to make sure i understand some basic stuff first:
how do i pass function A as a parameter to function B?
how do i call function A from inside B ?
Now for the big whammy:
I'm trying to do something along the lines of this:
jmp_buf buf;
buf.__jmpbuf[JB_PC] = functionA;
longjmp(buf,10);
Meaning that I want to use longjmp in order to go to a function. How should I do it?
You need to use a pointer to a function. The syntax for declaring a function pointer is:
rettype (*)(paramtype1,paramtype2,...,paramtypeN)
So, for example, we might have the following code:
char functionA(int x)
{
printf("%d\n",x):
return 'a';
}
char functionB(char (*f)(int), int val)
{
return f(val); // invokes the function pointer
}
int main(int argc, char* argv[])
{
char result = functionB(&functionA,3); // prints "3"
printf("%c\n",result); // prints 'a'
return 0;
}
Also, a side note, that while &functionA takes the address of functionA, it is actually not necessary to use the ampersand there... I personally do it, since I think it makes it more clear that it is a function pointer. You invoke a function pointer using the same syntax that you would when invoking a function.
As for using jump buffers, I believe what you are doing is not something that can be relied upon. If you want to create a jump buffer and invoke setjmp before invoking some function, then later invoke longjmp so that you return to immediately prior to the call, then that is well-defined. The actual definition and structure of jmp_buf, though, is implementation-specific. There are certain requirements that it has to meet (e.g. it has to be an array type, because setjmp has to be able to take it by value and yet modify it), but other than that, the specification for setjmp.h does not define the structure of jmp_buf. So, anything that attempts to manipulate jmp_buf directly is going to be specific to a particular platform.
Passing functionA as a parameter to functionB:
typedef void function_type(void);
void functionA(void)
{
printf("This is function A\n");
}
int main(int argc, char **argv)
{
functionB(&functionA);
return (0);
}
Calling function A from function B:
void functionB(function_type *func)
{
func();
}
Using longjmp() to go to a function. The best answer is "Don't do this" - there's almost always a better way to achieve the same aim. Can you explain the situation where you need this?