When you pass a struct to a function, is it pass by value (similar to
regular variables where the value gets cloned), or is it pass by
reference (similar to arrays where the actual variable is passed)? Can you give an example.
In C everything is pass by value, even passing pointers is pass by value.
And you never can change the actual parameter's value(s).
That is from K&R by the way. And I recommend to read that book. Saves you many questions you might post in the future.
A struct is passed by value:
struct S {
int a,b;
};
void f(struct S s) {
printf("%d\n", s.a+s.b);
s.a = 0; /* change of a in local copy of struct */
}
int main(void) {
struct S x = { 12,13};
f(x);
printf ("Unchanged a: %d\n",x.a);
return 0;
}
Online demo
You are passing it by value. Everything in a structure is copied.
Related
This question already has answers here:
How can I simulate OO-style polymorphism in C?
(13 answers)
Closed 6 years ago.
Suppose I have the following struct
struct Being{
int canFly;
int (*printFlying)();
}
And I want to do something like the following:
int main(){
struct Being * flyingThing = new_flyingThing();
struct Being * thingThatCantFly = new_Thing();
flyingThing->printFlying(); /* "I'm flying!" */
thingThatCantFly->printFlying(); /* "I can't fly!" */
}
It looks like I would need the printFlyingfunction to be able to access the canFly variable in the struct, but I don't know how to do this, or if this is possible.
Is there any way to get my code to do what I want? Thanks!!
I explained in the comments why this question is not a duplicate of the linked one.
C isn't an object-oriented language, so there's no automatic way for a function member to know which structure was used to call it.
Since each structure has its own function pointer, you can get the result you want by having them refer to different functions, which print the appropriate message, instead of getting it from the can_fly member.
int print_flying_thing() {
printf("I'm flying!\n");
}
struct Being *new_flyingThing() {
struct Being *thing = malloc(sizeof(struct Being));
thing->can_fly = 1;
thing->printFlying = print_flying_thing;
return thing;
}
int print_nonflying_thing() {
printf("I can't fly!\n");
}
struct Being *new_Thing() {
struct Being *thing = malloc(sizeof(struct Being));
thing->can_fly = 0;
thing->printFlying = print_nonflying_thing;
return thing;
}
The function pointed to by the printFlying pointer cannot access members of the containing struct Being structure unless it's given a parameter that refers to that structure. (Or it could access the structure in some other way, perhaps via a global variable, but a parameter is the cleanest way.)
Consider, for example, two objects of type struct Being, both having their printFlying pointer pointing to the same function. There's no way that function can tell which of the two objects it's associated with -- because it isn't associated with either of them.
C++ member functions can do that because they're given an implicit pointer parameter, referred to inside the function via the this keyword. C has no such feature.
You could probably create a macro that does something similar, but I doubt it would be worth the effort.
Have you considered just using C++?
For this particular example what you seem to really want is the ability to have a function pointer that points to two different functions, one to implement flying and one that implements not flying.
So the approach I would consider would be something like the following. I have not tried to actually compile this code but the sense of this is correct.
Also in your comments you mentioned about preventing changing the function pointer. You can do something like the following where a const is added to the struct definition for the function pointer and then using a clone of the struct with a cast.
Header file flying.h contents.
typedef struct _TAG_Being {
int (* const printFlying)();
} Being;
Being * new_flyingThing ();
Being * new_Thing();
Implementation or flying.c file.
#include "flying.h"
static int printFlyingThing()
{
printf (" I am a flying thing\n");
return 0;
}
static int printThing()
{
printf (" I am a thing\n");
return 1;
}
// use the same layout and members as Being above.
typedef struct {
int (* printFlying)();
} BeingX;
Being * new_flyingThing ()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printFlyingThing; // use the flying thing function
{
Being *q = (Being *)p;
return q;
}
}
Being * new_Thing()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printThing; // use the not flying thing function.
{
Being *q = (Being *)p;
return q;
}
}
Main or using .c file
#include "flying.h"
int main(){
Being * flyingThing = new_flyingThing();
Being * thingThatCantFly = new_Thing();
flyingThing->printFlying(); /* "I'm flying!" */
thingThatCantFly->printFlying(); /* "I can't fly!" */
}
If you have a need to access the actual Being object or variable in the printFlying() function then you will need to pass it as an argument.
For instance:
typedef struct _TAG_Being {
int xx;
int (*printFlying)(struct _TAG_Being *p);
} Being;
Then you would need something like:
Being * flyingThing = new_flyingThing();
flyingThing->printFlying(flyingThing); /* "I'm flying!" */
I have been trying to pass a struct as an argument, but I seem to have an issue with the different structs.
My goal is to create a generic function that takes a struct and then overwrites a field in particular struct.
struct information{
int number;
};
typedef struct information Jack;
typedef struct information Joe;
and then a function.
foo(struct information Name , int randomNumber) {
Name.number = randomNumber;
}
However, when I print Jack.number and Joe.number, it prints 0.
void main() {
int h =5;
foo(Joe,h);
foo(Jack,h);
printf("%d",Jack.number);
printf("%d",Joe.number);
}
Is there any way of solving this issue and create such a generic function?
Perhaps you should pass a pointer to your struct, like this:
foo(struct information *Name , int randomNumber) {
Name->number = randomNumber;
}
You would call your function like this:
foo (&Jack, 42);
[Edit] Oh, and there's something wrong with your declarations as well. Maybe you could declare your objects like this:
typedef struct informationStruct {
int number;
} Information;
Information Jack;
Information Joe;
and your function like this:
foo(Information *Name , int randomNumber) {
Name->number = randomNumber;
}
You are passing the struct by value. Whatever changes you make to Name in foo affects only the copy of the object in foo. It does not change the value of the object in the calling function.
If you want the change to take effect in the calling function, you'll need to pass a pointer to it. For that, you'll need to change the interface of foo.
foo(struct information* Name , int randomNumber) {
Name->number = randomNumber;
}
You'll need to change the call also to match the interface.
foo(&Joe,h);
foo(&Jack,h);
C passes structs by value (as every other argument type). If you want to see changes outside of the function, pass it by reference:
void foo(struct information *name, int randomNumber) {
name->number = randomNumber;
}
foo(&joe, 42);
Remember that C passes, values to function and not reference. So as everyone has mentioned,you could pass the address of the structure(which you want to modify) to the function and then the changes made to the structure inside that function would be automatically reflected in main function.
Is it safe to return a struct with array data member in C?
Something like
struct my_str {
int v[5];
};
struct my_str ret_stupid() {
struct my_str rval;
/*do something..*/
return rval;
}
I don't know why... I'm a bit puzzled. (I've tried and it does work). Is there some standard explaining how this operation actually is performed? I mean the mechanism of struct return and assignment too could be useful to understand better.
Is it safe to return a struct with array data member in C?
Yes.
struct are copied bit-wise. Bit-wise copying a struct that has an array as a member makes sure that the copy of struct has a copy of the array too.
Structures are a lot like arrays.
They can contain variables of any kind.
Their addresses will be sorted stacked as long as you leave no gaps or invoke the preprocessor directive #pragma pack
"Is it safe", depends of the code hiding there..
/do something../
But in general - yes. This is just a function of type struct my_str and has to return struct my_str
What the structure contains - doesn't matter. Still safe to use.
You can return a structure from a function without any problems. It's a well-defined part of the language. You can pass structures to functions as well - a structure is exactly the same as any built-in type for purposes of parameter passing, return values, and assignment.
Here's an example
#include <stdio.h>
int func(int x)
{
int r = x;
return r;
}
int main(void)
{
int x = 12;
int y = func(x);
printf("%d\n", y);
return 0;
}
If it weren't for the array member, the return would be an "rvalue", a value that is just a copy of the value that you have inside the return expression. If you have
struct toto {
double a;
};
struct toto g(void) {
struct toto retval = { 0.0 };
...
return retval;
}
int main(void) {
printf("%g\n", g().a);
}
The argument of the printf call sees a copy of the variable retval that is used inside the function. g().a calls the function and uses the .a field of the return value.
This return value is and
entity that is not an object but only lives because of its "value", called rvalue in the C jargon. It only can be found on the RHS of an assignment, thus the "r" in "rvalue".
The case that you are giving is actually specially treated, because a "value" is not sufficient for all use cases of the array. So this generates a so-called "object with temporary lifetime". This is needed because if you'd do ret_stupid().v[2] the [] operator wants to have a pointer, and a pointer can only point to an object, not a value.
These objects only "live" inside the expression that contains the function call, and even though they are not const qualified you are not allowed to modify them.
So all in all, this is a corner case of C, and you shouldn't abuse it.
In C component selection, what is the benefit of structure-returning function? for example:
struct S {
int a, b;
} x;
Why is it that I can assign the above struct as a function as shown below, Is there any benefit of doing this?
extern struct S f(); /* Why is this neccesary? */
x = f(); /* Is this accurate */
Open my eyes on this guys.
It's just a function that happens to return a struct. There's nothing more to it than that. You wouldn't be surprised to see a function return an int, why be surprised when one returns a struct?
As an aside, the extern is superfluous here because that is the default storage class for functions.
It is useful so that you can return multiple values from a function.
For example, you can use it like this
struct Point {
int x;
int y;
};
struct Point getMousePos()
{
struct Point pos;
pos.x = 567;
pos.y = 343;
return pos;
}
int main()
{
struct Point mouse_pos = getMousePos();
printf("Mousepos %d,%d\n", mouse_pos.x, mouse_pos.y");
}
The function can be forward declared with extern (this would normally be done in a header file), so that other functions know its prototype i.e. its parameters and return type, even if the function is itself defined in another file.
If you get a copy of a struct instead of a pointer to it, you know that you never have to worry about free()ing it, or whether there are any data races where one thread is writing to the struct while another reads from it, or whether the pointer returned by the function will be invalidated by some action that might be outside of your control.
New to StackOverflow and new to C. I'm trying to take a struct as a parameter in a function 'add_fields', which adds the first two int fields 'a' and 'b' and puts the result in int field 'c'. Not getting anything from the compiler, so obviously I'm doing something wrong. I just don't know what. Any help would be appreciated.
#include <stdio.h>
struct add{
int a;
int b;
int c;
}
void add_fields(struct add *d){
d->c = a + b;
}
main(){
struct add data;
data.a = 1;
data.b = 2;
data.c = 0;
add_fields(data);
printf("%d + %d = %d", data.a, data.b, data.c);
}
You're very close, but variables a and b don't exist in that context, rather you need to access the fields via the pointer to struct d:
d->c = d->a + d->b;
Second, you need to pass a reference to the struct (since add_fields expects a pointer) when you call add_fields:
add_fields(&data);
The & indicates that you're going to pass the address of the variable data rather than the value.
Here is your corrected code:
#include <stdio.h>
struct add{
int a;
int b;
int c;
};
void add_fields(struct add *d){
d->c = d->a + d->b;
}
int main(){
struct add data;
data.a = 1;
data.b = 2;
data.c = 0;
add_fields(&data);
printf("%d + %d = %d", data.a, data.b, data.c);
return 0;
}
You forgot a semicolon after the struct definition.
I had to fix your add_fields function. You didn't use your struct for a and b.
You needed to pass a pointer into add_fields (hence the &) in the function call. By passing a pointer in, your changes in add_fields were reflected on the outside calling struct.
main always returns an int.
There are several issues:
In main, data is of type struct add. When you call add_field, you need to pass it a struct add* (that is, a pointer to a struct add). To get a pointer to data in main, you need to use the & operator:
add_fields(&data);
In add_fields, you need to use the "member access syntax" (the ->) to access a and b.
Two other minor issues: main should have a return type of int:
int main() { ...
and you need to place a semicolon after the closing } of a struct definition.
C is call by value language. When you pass data, you are passing a copy of the object of type struct add. In your add_fields field, you are accepting a pointer to the struct. Since you want to change the fields of the struct, you should pass the address of the data struct (and accept a pointer to it in add_fields). To do this,
add_fields(&data);
Also, in add_fields, you aren't have undefined variables (a and b). I assume they should be from the struct, as well?
You should be passing the memory address of the struct to the add_fields function.
add_fields(&data)
** Wow I was really slow on this one :P