C problem: Passing var defined in function stack - c

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.

Related

Why are pointers such a big deal in C?

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.

parameter passing in C function

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.

Passing an array to a function in c

I have a doubt regarding passing of arrays to a function.
consider the following code snippet.
void main()
{
int a[4]={10,20,30,40};
fun1(a);
}
void fun1(int a1[])
{
for(int i=0;i<4;i++)
{
printf("%d\n",a1[i]);
}
}
Passing an array is nothing but passing the address of the first location.
And I should pass the above array with its name(starting address of the array).
My doubt is since a[4] is an auto variable, it should die when it comes out of the main function and it should give the unexpected results(the pointer should be dangled).
But it is working fine.
I am very confused with this, can you please clear it off.
Even if we pass a single element int a as f(&a), it should not exist in the function f, if it is declared as automatic(local variable in main function).
Please clear this as well.
Yes, variable a will be out of scope when main() terminates.
But when fun1 is executing, main() has not reached termination yet, so the content of a is still perfectly valid.
What you are doing is fine. The array a does indeed go out of scope but by that point your function has finished so you don't have to worry about accessing data that is no longer around. If you have concerns about passing the variable as the array name (which is fine) you can always step through your code to ensure you are accessing the data you think that you are.
You could also make your function safer by passing an additional integer argument that specifies the size of your array rather than having it hard coded as 4. If you used the function you have and passed an integer array of length less than 4, it will be accessing out of bounds memory.
void fun1 ( int a1[]) is creating a copy of whatever array is coming into the function. So it will exist.
You can also vision it as a stack. A stack will be created for main() method. And since the fun1() is called from the main method, the stack of main method will destroy only when the stack for fun1() is destroyed.
int a[] in function declaration/definition is equal to const int *a so nothing bad will happen and no memory will be freed implicitly.

Returning struct in a c function

I have something like the folowing C code:
struct MyStruct MyFunction (something here)
{
struct MyStruct data;
//Some code here
return data;
}
would the returning value be a reference or a copy of the memory block for data?
Should MyFunction return struct MyStruct* (with the corresponding memory allocation) instead of struct MyStruct?
There is no such thing as a reference in C. So semantically speaking, you are returning a copy of the struct. However, the compiler may optimise this.
You cannot return the address of a local variable, as it goes out of scope when the function returns. You could return the address of something that you've just malloc-ed, but you'll need to make it clear that someone will need to free that pointer at some point.
It would return a copy. C is a pass-by-value language. Unless you specify that you are passing pointers around, structures get copied for assignments, return statements, and when used as function parameters.
It is returned as copy. BTW, you should not return it's reference because it has automatic storage duration ( i.e., data resides on stack ).
I have had problems with this (a function in a DLL returning a struct) and have investigated it. Returning a struct from a DLL to be used by people who might have a different compiler is not good practice, because of the following.
How this works depends on the implementation. Some implementations return small records in registers, but most get an invisible extra argument that points to a result struct in the local frame of the caller. On return, the pointer is used to copy data to the struct in the local frame of the caller. How this pointer is passed depends on the implementation again: as last argument, as first argument or as register.
As others said, returning references is not a good idea, as the struct you return might be in your local frame. I prefer functions that do not return such structs at all, but take a pointer to one and fill it up from inside the function.

C stack/scope, variable's lifetime after functions ends

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.

Resources