I have a function written in C
FindBeginKey(KeyListTraverser, BeginPage, BeginKey, key1);
BeginKey is a pointer before function invoking, and I didn't initiate it, like
BeginKey = NULL;
In the FindBeginKey() function, I assign BeginKey to another pointer, and try to print out the current address of BeginKey in the function, it works correct.
But when code returns from function, I try to print out the address of BeginKey again, it shows 0x0.
Why does this happen, and if I want to preserve the address assigned in the function, what should I do?
To pass a value out of a function you have to pass by reference rather than by value as is normally the case with C functions. TO do this make the parameter a pointer to the type you want to pass out. Then pass the value into the call with the & (address operand).
e.g.
FindFoo(FOO** BeginKey);
and call it:
FindFoo(&BeginKey);
and in the function:
*BeginKey = 0xDEADC0DE;
From what I understand, you are calling the function like:
FindBeginKey(KeyListTraverser, BeginPage, BeginKey, key1);
However, when you try to write at the BeginKey address, you're basically passing in a pointer to 0x00. Rather, you need to pass a pointer to BeginKey.
FindBeginKey(KeyListTraverser, BeginPage, &BeginKey, key1);
If this is isn't what you meant, it would certainly help if you posted a code sample.
If you want to modify a parameter in a subroutine, you should pass a pointer of the thing you wanna modify.
void subroutine(int* x) {
*x = 5; // will modify the variable which x points to
x = 5; // INVALID! x is a pointer, not an integer
}
I don't know what all the C parameter passing rules are now, so this answer might be a little dated. From common practice in building applications and libraries that those applications called, the return from a C function would contain status, so the caller of the function could make a decision depending on the status code.
If you wanted the function to modify its input parameters, you would pass those parameters by reference &my_val, where int my_val;. And your function must dereference my_val like this *my_val to get its value.
Also, for performance reasons, and address (by reference) might be preferable, so that the your application did not bother copying the parameter's value into a local variable. That prolog code is generated by the compiler. Single parameters, char, int, and so on are fairly straight forward.
I am so used to C++ that passing by reference in C++ does not require dereferencing. The compiler's code takes care of that for you.
However, think about passing a pointer to a structure.
struct my_struct
{
int iType;
char szName[100];
} struct1;
struct my_struct *pStruct1 = &struct1;
If the structure contains lookup data that is filled in once on initialization and then referenced throughout your program, then pass a pointer to the structure by value pStruct1. If you are writing a function to fill that structure or alter already present data, then pass a pointer to the structure by value. You still get to alter what the structure pointer points to.
If on the other hand you are writing a function to assign memory to the pointer, then pass the address of the pointer (a pointer to the pointer) &pStruct1, so you will get your pointer pointing to the right memory.
Related
Are function parameters real variables or are they variables that store another variable or what even are they exactly at this point. Pointer parameters are included too. If you put & in the argument then why do you even need to declare pointer parameter in the function if you already got the memory address with &? Does the pointer parameter actually store memory address afterall or not?
You may want to watch a video explaining how pointer parameters to functions work: https://www.youtube.com/watch?v=LW8Rfh6TzGg
But let me answer your specific questions...
Are function parameters real variables
Yes. But their scope is the body of the function; and their lifetimes are during invocations of the function: They come into existence when the function begins execution, and cease to exist when you return from the function.
or are they variables that store another variable
Variables can't store variables. Variables store values. (Pointer variables' values happen to be addresses.)
Pointer parameters are included too. If you put & in the argument then why do you even need to declare pointer parameter in the function if you already got the memory address with &?
Suppose you have a variable int x. Now, x is an integer, but &x is a pointer-to-an-integer - the address of the x variable.
In C, you can't define a parameter and have it represent a different variable elsewhere. What you can do is a pass an address of an external variable, then go through the address to read or write the value of that variable.
Does the pointer parameter actually store memory address after all or not?
It does actually store an address.
Are function parameters real variables
Yes. Inside a function, a parameter acts just like a local variable (that was initialized to the passed-in value at the top of the function).
i.e.
void foo(int a)
{
[...]
}
is logically equivalent to this (pseudocode):
void foo(...)
{
int a = /* the value that the caller called foo() with */
[...]
}
If you put & in the argument then why do you even need to declare
pointer parameter in the function if you already got the memory
address with &?
Placing & in the argument allows you to pass a pointer to the value, rather than passing the value itself.
If you want to pass a pointer, then your function needs to accept a pointer type as its argument, otherwise your call to the function won't compile.
Does the pointer parameter actually store memory address afterall or not?
Yes, it does.
I understand the premise of pointers, but I find it very annoying, and I don't get why it's considered useful;
I've learned about pointers, and the next thing I know, I start seeing bubbles, asterisks, and ampersands everywhere.
#include <stdio.h>
int main () {
int *ptr, q;
q = 50;
ptr = &q;
printf("%d", *ptr);
return 0;
}
why is this important or useful?
First, parameters passed to a function can only be primitives(int, char, long....), structs or pointers. Then if you need to pass a more complex element like an array (strings) or a function, you have to pass a reference to this element.
The second things that I can quickly think of is: parameters are always passed by "value". This means the called function only get a copy of your variable. So, modifications will only affect the copy, the original variable will remain unchanged.
If you pass a variable by "reference" with a pointer, the pointer itself is immutable but as it is a reference to the original var, any modification to the pointed element will also affect the var in the caller function.
In other words, if you want to create a function that can alter a variable, you have to pass it a pointer to that variable to achieve this.
I'm wondering if it is always better to use pointers. I have a structure with only one byte (or some integers ).
This structure contains i.e. parameters to a routine and will be passed there.
If I don't use pointers (inside of the struct), but pass this struct by pointer, would the change (for logPrio) made in main_loop be visible outside (i.e in main)?
Please see this sample to get me:
typedef struct mainloop_param_t
{
unsigned char *logPriop;
//or versin w/o pointer
unsigned char logPrio;
}mainloop_param_t;
int main()
{
mainloop_param_t mlparams;
unsigned char logPrio;
mlparams.logPriop = &logPrio;
// or nothing cause mlparams.logPrio already initialized
// would mlparams.logPrio be a copy or original?
g_timeout_add (5000, (GSourceFunc)main_loop, &mlparams);
}
If I don't use pointers (inside of the struct), but pass this struct by pointer, would the change (for logPrio) made in main_loop be visible outside (i.e in main)?
Yes, after you have passed the address of mlparams, every change made in main_loop can be visible in main, regardless of whether a pointer or an variable inside mlparams.
I guess your probloem is when a pointer should be used. In my opinion, pointer is just a tool to access data, it should not be a problem of itself. The important things are "which place the data should be?" and "how does programs access the data?"
The followings are parts of usages:
data is here(locally) and will be accessed here --> just define and use an local variable
data in somewhere(another scope, e.g. outside) and will be accessed here --> define a pointer that point to the data and access tha data via operator *
data is here and will be accessed in somewhere(another scope, e.g. inside) --> define an variable and pass the address of the variable somewhere
data in somewhere and will be accessed in otherwhere --> define a pointer that point to the data and pass the pointer otherwhere
sometimes you need some data that may be in a large amout, insdead of copying all of them to stack(might cause overflow), it's better to copy an address of the beginning of the data. The copy of the address is just a pointer.
I'm wondering if it is always better to use pointers.
Use pointers when it is needed. Unnecessarily use of it may cause some confusion later to you and others readers.
If I don't use pointers, would the change (for logPrio) made in main_loop be visible outside (i.e in main)?
In case of global variable and structs YES, Otherwise NO.
unsigned char logPrio;
mlparams.logPriop = &logPrio;
In this code, it doesn't make any sense to use a pointer. The change happens in main and will be visible to g_timeout_add since you pass this struct to that function.
I think you are confusing things with how parameters are passed by pointer to a function. If you have a function like
void func (int x)
{
x = 2;
}
then the original variable passed to the function is not altered, because x inside the function is a copy of the variable from the caller.
int var = 1;
func(var);
printf("%d", var); // will print 1
If you want to alter the variable's value, you would have to write the function like:
void func (int* x)
{
*x = 2;
}
int var = 1;
func(&var);
printf("%d", var); // will print 2
int myfunc2(struct MyStruct st2[])
{
return 0;
}
int myfunc()
{
struct MyStruct st;
myfunc2(&st);
return 0;
}
Is this a pure bug? Or it is not a bug if it didn't call another function and st is not passed to another function in myfunc2. Can the st be the same one referenced by myfunc2 when myfunc2 get the pointer and pass it to another function?
This is perfectly valid code. You can pass it to any number of functions from myfunc2. The variable you allocated on stack will remain valid until it goes out of scope from myfunc
It depends on whether MyStruct is defined at a scope visible to myfunc2() or not, and what parameter myfunc2() is expecting.
Edit: with your edit to include a function prototype, it is certainly perfectly valid code.
There's nothing wrong with passing the address of a local variable to a function, but remember that the variable goes out of scope (and the pointer ceases to be valid) when the containing function returns. Be careful if myfunc2() might save the pointer for later use.
The code you showed is valid if you used myfunc2 in the correct way. You need to tell us the semantics (or show the implementation) of myfunc2 in order to let us say if anything is ok.
Passing the address of a local variable instead of an array is perfectly fine and equivalent to passing an array of size 1.
The problem with your code, however, is that myfunc2() has no way of knowing the size of the array passed to it. I guess it's okay if it uses only the first element of array, but then it should probably be declared to accept a pointer, not an array.
I am a bit confused about the behaviour of a C program from another programmer I am working now with. What I can not understand is the following:
1) a variable is defined this way
typedef float (array3d_i)[3];
array3d_i d_i[NMAX];
2) once some values are assgined to all the d_i's, a function is called which is like this:
void calc(elem3d_i d_element);
which is called from main using:
calc(d_i[i]);
in a loop.
When the d_i's are initialized in main, each element gets an address in memory, I guess in the stack or somewhere else. When we call the function "calc", I would expect that inside the function, a copy of the variable is created, in anoother address. But I debugged the program, and I can see that inside the function "calc", the variable "d_elemt" gets the same address than d_i in main.
Is it normal or not?
I am even more confused because later there is call to another function, very similar situation except that now the variables are float type and also an array of them is initialized, and inside the function, the variables are given a different address than the one in main.
How can this be? Why the difference? Is the code or the debugger doing something weird?
Thanks
Arrays are passed by reference in C, while simple values will be passed by value. Or, rather, arrays are also passed by value, but the "value" of an array in this context is a reference to its first element. This is the "decay" Charles refers to in his comment.
By "reference", I mean pointer of course since C doesn't have references like C++ does.
C does not have a higher-level array concept, which is also why you can't compute the length of the array in the called function.
It's the difference between pointers and variables. When you pass an array to a function you are passing a pointer (by value). When you pass a float, you are passing a float (by value). It's all pass by value, but with the array the value is the address of the pointer.
Note that "passing arrays" is the same as passing pointers and that, in C all parameters are passed by value.
What you see in the different functions is the pointer value. The pointer itself (the parameter received by the function) is a different one in each function (you can check its address)
Imagine
int a = 42, b = 42, c = 42;
If you look at a, b, or c in the debugger you always see 42 (the value), but they're different variables.
As others have noted, everything is passed by value. However, that can be misleading for arrays. While similar to pointers, arrays are not pointers. Pointers are variables which hold addresses. Arrays are blocks of memory, at a particular address. For arrays, there is no separate variable which holds the address, like a pointer. When you pass an array as an argument to a function, or get it's address by assigning the name (without the [] indexing) to a pointer, then you do have it's address contained in a variable. So, what is "passed by value" is a pointer, not an array, even though you called the function with an array as an argument. So the following are equivalent:
void func1(char *const arg);
void func2(char arg[]);