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.
Related
I have a global variable called: char clientes_dni[]. I am calling (from the main) a function like: comprobarExistenciaDNI(clientes_dni). My function comprobarExistenciaDNI is:
bool comprobarExistenciaDNI(char DNI[]) {
/// Change to lower DNI last word
DNI[8] = tolower(DNI[8]);
return (true);
}
If my var has the value '11111111J', after function the value is '11111111j'. I am not working with global variable, only with the local variable so... Why value of clientes_dni is changed?
Thank you.
I think the problem is that DNI is an array (a pointer) so you are actually modifying the contents of the array when you say
DNI[8] = tolower(DNI[8]);
It's like when you send a variable by reference to a function.
Do you have experience with pointers?
Edit 1:
I'll give you a quick spoiler. A pointer is the value of a memory address. Like i said, an array is a pointer, this one "points" to the first element of the array in memory (the elements are one next to each other) so when you send clientes_dni you are sending the location of the first element to the comprobarExistenciaDNI function. The function then modifies the value (the contents) of that memory address. That's why it gets modified in the main scope, because you modified the content of the memory address.
It is different when you send a variable of any other data type, you are sending a copy of the variable instead of the variable itself.
Arrays are passed by the address of the 1st element. In most use cases (there are few exceptions like sizeof operator), the name of an array (let's say A) is synonymous with &A[0]. structs are passed by value, if that's what you are looking to do (wrap the array in struct).
Your local variable is of pointer type and it refers to a global string. 'Array' arguments of functions are not allocated and deep-copied but rather bound to addresses.
I wanted to know what's the difference between these two versions of the main() code in C:
int main() {
uint32_t a;
f(&a);
}
and
int main() {
uint32_t *a;
f(a);
}
for a function
void f(uint32_t *pointer) {
// ...
}
In your first example, you pass a pointer to uninitialized variable a. f() could store a value there, for instance, and main() would be able to use that value later.
In your second example, you pass an uninitialized pointer a. f() can't do anything useful with it.
In the first version you pass a pointer to an un-initialized variable to f().
Don't, unless f()'s task is to initialize the variable.
In the second version you pass an uninitialized pointer to function f().
Don't.
wee pointer questions!!!
Ok so you know that the function f needs to take a pointer which is exactly as it sounds an address to that actual location in memory. For the first example(f(&a)) you have to pass the address because it lives inside the stack and really isn't shared anywhere outside the life of the function. so when the function returns the memory is destroyed and no longer available. the value of the pointer is not passed just the pointer to the value is passed. which can cause problems because if you change that value then all the things that "point to it" are now changed.
Now for the second one you get the memory from the heap or where ever but that stores the address of the value not the actual value so you can manipulate it and return nothing and the value is still there.
They are defining different types of variables, without initialization.
uint32_t a; defines uint32_t variable on the stack and the function call will pass its address to the f() function.
uint32_t *a; defines a pointer on the stack and pass its value to the function. The pointer is not initialized, thus it could point to any block and any attempt to access that address will result into undefined behavior.
From the perspective of the f() function, it sees pointer values passed to it. In the first call, it can use that address, while in the second, it cannot.
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.
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[]);
void someFunc()
{
int stackInt = 4;
someOtherFunc(&stackInt);
}
Is it the case that stackInt's address space could be reallocated after someFunc ends, making it unsafe to assume that the value passed to someOtherFunc represents the stackInt variable with value 4 that was passed to it? In other words, should I avoid passing stack variables around by address and expecting them to still be alive after the function they were initialised in has ended?
Yes, definitely.
You don't have to avoid passing stack-allocated variables by reference/pointer altogether, though, just storing pointers or references to stack-allocated variables.
After someFunc() returns and another function is called, the space that was used for stackInt will be used for some other variable in the new function. Therefore, the function someOtherFunc() cannot safely assume that if it keeps a copy of the pointer it is passed, that pointer will remain valid. If it stashes a copy of the value that was pointed at, that is fine.
So, although it is fine to pass stack variables around by address (so, for example someOtherFunc() could modify the value of stackInt and, if there was code in someFunc() that accessed it after the call, the value might not be 4 still), it is not safe to store the pointer and expect it to point to anywhere valid after someFunc() returns.
It is absolutely fine to pass stack variables as parameters in all possible ways
The stack allocated variables will be overwritten only when the function declaring those variables is completed its execution.
So until you return from someFunc() there is no harm to stackInt.
As long as you don't spawn new thread from someOtherFunc and use stackInt there, this will work.