Programming language C - c

Can a function be used to copy elements from one array and save it into another array without returning the array to main.Because once we come out of a function all the variables local to it are lost.e.g
void copy(char to[],char from[])
{
int i;
while((to[i]=from[i])!='\0')
++i;
}
How does this code work?Because after copying elements from to array to from array.After the function is executed all the variables must be lost and nothing
must be saved in from array after function is executed.Please clarify my doubt.

The arrays are passed by pointers (the way references are used in C). So when the data is modified in the body of the function, the calling function can access the modified data.
After the function is executed all the variables must be lost and
nothing must be saved in from array after function is executed.
True, objects that have liftetimes within the lifetime of the function will be lost when the function exists. However the function's lifetime has no effect on objects that have existed before it or after it.

This line
void copy(char to[],char from[])
doesn't actually take two arrays by value. Instead, the [] decays to a pointer, what you've actually written is:
void copy(char* to, char* from)
This is because of array-pointer-equivalence. The language couldn't tell how big the arrays its going to need to copy would be when it compiled the function, since it could be different each time.
Thus only the pointers, to and from, are local, the data they point to is the same data that was pointed to in main.

After the function is executed all the variables must be lost and nothing must be saved in from array after function is executed.
Not exactly.
Generally C uses call-by-value, which means the function deals with copies of the parameters and so cannot modify them.
In order to modify the variable directly, you need to pass the address of the variable (ie the pointer to it), the function then access the variable via the pointer and can modify it directly.
That's also the case when you pass an array to a function, the value passed the the function is the location/address of the first element of the array. The function itself can then access and alter any element of the array.
In short, it's totally OK for your function copy to modify array to. And usually you should make from as const because you are not changing it inside the function. So the prototype should look like this:
void copy(char to[], const char from[]);

While local variables are lost at function end (scope-close), this only applies to to and from themselves -- NOT what they might point to.
BTW, your code is broken, try this instead:
void copy ( char * to, char * from ) {
while ((*to = *from) != '\0') {to++; from++;}
}
Both this version and yours blindly assumes that to is long enough to hold the result. This is potentially dangerous code.

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.

Why is a string copy function just assigning the pointer not working?

Consider this implementation of strcpy:
void my_strcpy(char target[], char source[])
{
target = source;
}
int main(void)
{
char target[20];
char source[] = "Source String";
my_strcpy(target, source);
printf("Target: %s", target);
return 0;
}
This doesn't work and its made me question my understanding of strings and arrays in C.
Here's my reasoning: target and source are really just pointers to the first elements of arrays, ie. target == &target[0] and source == &source[0]. When I set target = source, I'm pointing the pointer target at the same memory address where the pointer source is pointed at.
Now when I printf target, it should also print "Source String". But it doesn't.
Can someone explain why?
void my_strcpy(char target[], char source[])
{
target = source;
}
What you do here is, as you wrote, pass the pointers to the function. But the pointers themselves are passed by value, so the function has it's local copies of these pointers. The target inside the function stops existing as soon es the function exits.
To actually modify pointers in a function, you would have to pass a pointer to this pointer, e.g. like this:
void my_strcpy(char *target[], char source[])
{
*target = source;
}
Note that this still wouldn't work with your program, because in main() you declare an array. The address of a declared array cannot be changed. This is because an array is not the same as a pointer (as you can often read in poorly written C tutorials) but is just implicitly converted to a pointer to its first element when you pass it to a function. So, writing char *target in your main(), this would work, calling the function like my_strcpy(&target, source);.
Also note that this is in no way a copy, so the naming of your function is semantically wrong. A real copy function would look like this:
void my_strcpy(char *target, const char *source)
{
while (*target++ = *source++);
}
copying the individual characters until hitting a \0 character (then the expression would evaluate to 0 and the while loop would stop). This super-simple implementation leaves the burden to provide enough storage for target and to make sure source is actually 0-terminated to the caller, but it is indeed more or less what the standard C library's strcpy() does.
edit: I just changed your function signature a bit -- the first change is a matter of taste, replacing identifier[] by *identifier. I like to do this because this is what happens internally anyways, so it makes clearer what the function actually takes. The second one is adding a const where appropriate: Your function never changes what is pointed to by source, so you should make this explicit -- this way the compiler can catch more errors for you.
Two things you need to keep in mind:
C uses pass-by-value.
You cannot change the address of an automatic array.
Now,
my_strcpy(target, source);
is the same as
my_strcpy(&target[0], &source[0]);
which passes the address of first element of both the arrays and
void my_strcpy(char target[], char source[])
is the same as
void my_strcpy(char* target, char* source)
where target points to the address of the first element of the array target in main and source points to the address of the first element of the array source in main.
So,
target = source;
simply changes the location where target points to. Now, both target and source points to the same memory location, i.e, to the address of the array source in main. This doesn't have any effect on either of the arrays in main as C uses pass-by-value. Both the pointers in the function have different addresses as that of the array.

What happens to an array during recursion in C?

In the following code I try to print all paths from the root to leaves in a Binary Tree.
If I write a recursive function as follows :
void printPath(BinaryTreeNode * n, int path[],int pathlen)
{
//assume base case and initializations taken care of
path[pathlen++] = n->data;
printPath(root->left,path,pathlen);
printPath(root->right,path,pathlen);
}
(I have purposefully removed base cases and edge cases handling to improve readability)
What happens to the path array? Is it just one global copy that gets modified during each recursive call ?Does the pathlen variable overwrites some of the path values, giving the feeling that each stack frame has it's own local copy of path, since pathlen is local to each stack frame?
Passing around a int[] variable is really almost like passing a int* around. The first invocation of the recursive function passes the real int[] which is nothing more than an address in memory, that's the same address used in every recursive call.
Basically if you place a debug print, eg
printf("%p\n", path);
in your recursive function you will see that the address is always the same, it doesn't change nor it gets modified. The only thing that is pushed onto the stack frame during the invocation is the address of the array, which nonetheless remains is always the same.
Welcome to array-pointer-decay. When you pass around an array, two distinct things happen:
When you declare a function to take an array parameter, you are really defining the function to take a pointer parameter. I. e., the declaration
void foo(int bar[]);
is perfectly equivalent to
void foo(int* bar);
The declaration of the array has decayed into a declaration of a pointer to its first element.
Whenever you use an array, it also decays into a pointer to its first element, so the code
int baz[7];
foo(baz);
is again perfectly equivalent to
int baz[7];
foo(&baz[0]);
There are only two exceptions, where this array-pointer-decay does not happen: the statements sizeof(baz) and &baz.
Together, these two effects create the illusion that arrays are passed by reference, even though C only ever passes a pointer by value.
The array-pointer-decay was invented to allow the definition of the array subscript operator in terms of pointer arithmetic: the statement baz[3] is defined to be equivalent to *(baz + 3). An expression which tries to add 3 to an array. But due to array-pointer-decay, baz decays into an int*, on which pointer arithmetic is defined, and which yields a pointer to the fourth element in the array. The modified pointer can then be dereferenced to get the value at baz[3].
void printPath(BinaryTreeNode * n, int path[],int pathlen);
compiler really looks at that like this
void printPath(BinaryTreeNode * n, int *path, int pathlen);
what happens to the path array? Is it just one global copy that gets modified during each recursive call
Nothing. The same path gets passed around, since in C array passing is just a pointer copy operation; and no, it isn't a global copy, but a parameter passed to the first call of the function, and will almost always live on the stack.
and the pathlen variable overwrites some of the path values giving the feeling that each stack frame has it's own local copy of path since pathlen is local to each stack frame?
Since you modify the value of the array elements and not the pointer pointing to the beginning of the array, nothing changes what path itself is pointing to (which is the array all the time). Like like you said it may give a feeling (particularly if you're used to that construct in other languages), but in reality only the same path gets passed around.
Aside: You don't seem to handle the exit condition and as it stands it'll be an infinite loop and mostly probably undefined behaviour when you start modifying elements that are out of the array's bounds.

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.

C: Passing Struct to a Function doesn't result in a call by value operation

I have the following problem with a program which I wrote in Visual C++ and I hope that anyone can help me please:
typedef struct spielfeld
{
int ** Matrix;
int height;
int width;
Walker walker;
Verlauf history;
} Spielfeld;
void show(Spielfeld fieldToShow); //Prototype of the Function where I have this
//problem
int main(int argc, char *argv[])
{
int eingabe;
Spielfeld field;
//Initialize .. and so on
//Call show-Function and pass the structure with Call by Value
show(field);
//But what's happened? field.Matrix has changed!!
//can anyone tell me why? I don't want it to become changed!
//cause that's the reason why I pass the field as Call by Value!
}
void show(Spielfeld fieldToShow)
{
//Here is the problem: Alltough the parameter fieldToShow has been passed
//with call by value, "fieldToShow.Matrix[0][0] = 1" changes the field in
//main!!
fieldToShow.Matrix[0][0] = 1;
//Another try: fieldToShow.walker.letter only affects the local fieldToShow,
//not that field in main! That's strange for me! Please help!
fieldToShow.walker.letter = 'v';
}
When you pass the structure in, you are passing it in by value. However, the matrix within it is implemented as a pointer to pointer to int. Those pointers are references, and so when you modify the value referenced by them in your function, the same value is referenced by the original structure in main.
If you want to pass these objects by value, you need to do a deep copy yourself, in which you allocate a new matrix, and copy all of the values from the original matrix into it.
As Drew points out, in C++, the preferred way to implement that deep copy is via a copy constructor. A copy constructor allows you to perform your deep copy any time your object is passed by value, without having to explicitly copy the object yourself.
If you are not ready for classes and constructors yet, you can simply write a function, perhaps Spielfeld copySpielfeld(Spielfeld original), that will perform that deep copy; it will essentially be the same as your initialization code that you elided in your example, except it will take values from the Spielfeld passed in, instead of creating a new Spielfeld. You may call this before passing your field into the show function, or have the show function do it for any argument passed in, depending on how you want your API to work.
You're copying the pointer when you pass fieldToShow. Pass-by-value does not perform a deep copy, so both the Spielfeld in an invocation of show(...) and main(...) (although distinct) have the same value for Matrix.
Fixing this is non-trivial. Probably the easiest thing to do would be to change show(...) to pass-by-reference (using a Spielfeld* basically) and make an explicit copy at the start of the function.
When your Spielfeld object is copied:
The copy has its own "walker", which is a copy of the original's "walker". Since walker is a struct, that means you have two structs.
The copy has its own "Matrix" member, which is a copy of the original's "Matrix" member. But Matrix is a pointer, which means you have two pointers. A copy of a pointer points to the same thing the original points to.
So, modifications to the contents of the copy's walker don't affect the original, because they have different walkers. Modifications to the contents of the copy's matrix do affect the original, because they share the same matrix.
The structure is begin passed by value, but since it contains a pointer (the matrix) what that pointer is pointing to can be changed by anyone that has access to the structure. If you don't want this to happen, you can make the pointer const.
As interesting trivia: this is how call by value works in java. Object references are always passed by value. If you manipulate the objects to which these references point tough it will feel like call by reference happened.
Has really nothing to do with your question but maybe you find that interestring.
Happy hacking

Resources