Passing a struct as an argument - c

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.

Related

Pass a Struct to a Function

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.

How to pass a pointer to a struct declared inside another struct as a function parameter?

In one of my applications written in C I have a struct declared as a member of another struct:
struct _test
{
int varA;
//...
struct _small
{
int varB;
//...
} small;
} test;
Now I want to create a function that access varB above, but I don't want it to access the entire structure test, that is, I don't want to do:
#include <relevant_header>
void myFunction()
{
test.small.varB = 0;
}
instead, I want to pass only the small structure as a parameter to that function; something like this:
#include <relevant_header>
void myFunction(struct _test::_small* poSmall)
{
poSmall->varB = 0;
}
The problem is I don't know how to do this, that is, the above code doesn't compile right (I suppose it's C++ syntax only). So how may I do this in a C code - pass a pointer to a struct that was declared inside another struct? I wasn't able to find anything about this both in SO as well as in Google in general.
Just do:
void myFunction(struct _small *poSmall)
{
poSmall->varB = 0;
}
The scope of struct _small is not limited to its outer structure.

Modifying method to accept different type of parameters in C programming

typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
} struct1;
typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
int struct_variable_2c;
} struct2;
typedef struct1 *struct1_ptr;
typedef struct2 *struct2_ptr;
static void sampleFunction(struct1_ptr valueToInsert){
//this code does some stuff here
}
int main(){
struct1_ptr struct1_var = (struct1_ptr) malloc(sizeof(struct1));
strcpy(struct1_var->struct_variable_1a, "some value");
strcpy(struct1_var->struct_variable_1b, "some value");
sampleFunction(struct1_var);
return 0;
}
I have a sample code in C programming as shown above. In the main method, I am trying to pass a variable of type struct1_ptr for sampleFunction method call.
This works like a charm. But when I want to pass a variable of type struct2_ptr, the compiler is throwing error. Basically, I am java developer. I want to reuse this sampleFunction method for any variable type in its parameter in general. Kindly help me in this.
You could emulate inheritance in C like this:
typedef struct
{
char struct_variable_1a[10];
char struct_variable_1b[12];
} struct1;
typedef struct
{
struct1 parent; /* Must be first element! */
int struct_variable_2c;
} struct2;
And then call like this:
sampleFunction((struct1_ptr)ptr_to_struct2);
or (I would favor this, because there's no cast):
sampleFunction(&ptr_to_struct2->parent);
Just note that you won't be able to access members of struct2 in function without casting it back.
These work for simple structures, but if you do anything more complex, using C++ would be more approriate.
unfortunately C does not support method overloading / polymorphism. So you have to write your own methodology.
one is, to give the type as a first parameter to every overloaded function. Inside the function you walk along with a simple switch-case to jump to the original function implementation (like struct1_sampleFunction() and struct2_sampleFunction()).
another is, to put an RECORDCORE struct at the beginning of every struct and fill the type into this RECORDCORE, so each function can dispatch according to this data.
in both cases you have to change the prototype from "struct1_ptr value" to "void *value"
change your function from:
static void sampleFunction(struct1_ptr valueToInsert){
//this code does some stuff here
}
to:
static void sampleFunction(void* valueToInsert){
//this code does some stuff here
}
If you want to identify the type of the structure add a second parameter to your function that contains the size of the struct.
//Edit:
Inside the function you have to cast your variable back to the structure you want to use. for example:
strcpy(((struct1_ptr)valueToInsert)->struct_variable_1a, "some value");

Pointer at function: access the data inside a structure?

I listed some example code below and the question is if there is a way for the function_name to access the value of number from struct_name?
typedef struct struct_name {
int number
void (*func)();
} * struct_name_ptr;
void function_name() {
//access number from struct
}
main() {
struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func(); //can it print the value of the number in the structure above?
}
Uh - no.
A struct can certainly contain a function pointer. But the function you call wouldn't have any knowledge of the struct. Unless you passed a pointer as a function argument, or made the struct global.
With my limited knowledge of programming, I don't think this is possible. Though the struct contains a function pointer, the address of the function assigned to it is different and I don't think there will be anyway for it to access it unless you pass it as an argument.
Well, two things, struct_name->number should have a value, and it either needs to be in the same scope as &function_name or it needs to be explicitly passed. Two ways to do it:
/* Here is with a global calling struct */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
struct struct_name newobject = { 0 };
void function_name() {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject->func=&function_name;
newobject->func();
}
/* And one with a modified function_name */
#include<stdio.h>
typedef struct struct_name {
int number;
void (*func)();
} * struct_name_ptr;
void function_name(struct_name) {
printf("%d",struct_name);
}
void main() {
struct struct_name_ptr newobject;
newobject.number = 0;
newobject->func=&function_name;
newobject->func(newobject);
}
No, a pizza won't ever know what the pizza delivery guy, who delivered it, looks like.
A regular function is just an address in memory. It can be called using a function pointer like in this case. In any case: The function won't know how it was called. In particular it won't know that it was called using a function pointer that's part of (a piece of memory corresponding to) some struct.
When using a language with classes like C++, member functions will have a hidden argument which is a pointer to the class instance. That's how member functions know about their data.
You can 'simulate' a simple OOP in plain C, for your example like:
typedef struct {
int number;
void (*func)();
} class;
void function_name(class *this) {
printf("%d",this->number);
}
#define CALL(c,f) c.f(&c)
int main() {
class object={12345,function_name};
CALL(object,func); // voilá
}

Passing struct to function

I'm a new C programmer and I wanted to know how I can pass a struct through to a function. I'm getting an error and can't figure out the correct syntax to do it. Here is the code for it....
Struct:
struct student{
char firstname[30];
char surname[30];
};
struct student person;
Call:
addStudent(person);
Prototype:
void addStudent(struct student);
and the actual function:
void addStudent(person)
{
return;
}
Compiler errors:
line 21: warning: dubious tag declaration: struct student
line 223: argument #1 is incompatible with prototype:
This is how to pass the struct by reference. This means that your function can access the struct outside of the function and modify its values. You do this by passing a pointer to the structure to the function.
#include <stdio.h>
/* card structure definition */
struct card
{
int face; // define pointer face
}; // end structure card
typedef struct card Card ;
/* prototype */
void passByReference(Card *c) ;
int main(void)
{
Card c ;
c.face = 1 ;
Card *cptr = &c ; // pointer to Card c
printf("The value of c before function passing = %d\n", c.face);
printf("The value of cptr before function = %d\n",cptr->face);
passByReference(cptr);
printf("The value of c after function passing = %d\n", c.face);
return 0 ; // successfully ran program
}
void passByReference(Card *c)
{
c->face = 4;
}
This is how you pass the struct by value so that your function receives a copy of the struct and cannot access the exterior structure to modify it. By exterior I mean outside the function.
#include <stdio.h>
/* global card structure definition */
struct card
{
int face ; // define pointer face
};// end structure card
typedef struct card Card ;
/* function prototypes */
void passByValue(Card c);
int main(void)
{
Card c ;
c.face = 1;
printf("c.face before passByValue() = %d\n", c.face);
passByValue(c);
printf("c.face after passByValue() = %d\n",c.face);
printf("As you can see the value of c did not change\n");
printf("\nand the Card c inside the function has been destroyed"
"\n(no longer in memory)");
}
void passByValue(Card c)
{
c.face = 5;
}
The line function implementation should be:
void addStudent(struct student person) {
}
person is not a type but a variable, you cannot use it as the type of a function parameter.
Also, make sure your struct is defined before the prototype of the function addStudent as the prototype uses it.
When passing a struct to another function, it would usually be better to do as Donnell suggested above and pass it by reference instead.
A very good reason for this is that it makes things easier if you want to make changes that will be reflected when you return to the function that created the instance of it.
Here is an example of the simplest way to do this:
#include <stdio.h>
typedef struct student {
int age;
} student;
void addStudent(student *s) {
/* Here we can use the arrow operator (->) to dereference
the pointer and access any of it's members: */
s->age = 10;
}
int main(void) {
student aStudent = {0}; /* create an instance of the student struct */
addStudent(&aStudent); /* pass a pointer to the instance */
printf("%d", aStudent.age);
return 0;
}
In this example, the argument for the addStudent() function is a pointer to an instance of a student struct - student *s. In main(), we create an instance of the student struct and then pass a reference to it to our addStudent() function using the reference operator (&).
In the addStudent() function we can make use of the arrow operator (->) to dereference the pointer, and access any of it's members (functionally equivalent to: (*s).age).
Any changes that we make in the addStudent() function will be reflected when we return to main(), because the pointer gave us a reference to where in the memory the instance of the student struct is being stored. This is illustrated by the printf(), which will output "10" in this example.
Had you not passed a reference, you would actually be working with a copy of the struct you passed in to the function, meaning that any changes would not be reflected when you return to main - unless you implemented a way of passing the new version of the struct back to main or something along those lines!
Although pointers may seem off-putting at first, once you get your head around how they work and why they are so handy they become second nature, and you wonder how you ever coped without them!
You need to specify a type on person:
void addStudent(struct student person) {
...
}
Also, you can typedef your struct to avoid having to type struct every time you use it:
typedef struct student{
...
} student_t;
void addStudent(student_t person) {
...
}
Instead of:
void addStudent(person)
{
return;
}
try this:
void addStudent(student person)
{
return;
}
Since you have already declared a structure called 'student' you don't necessarily have to specify so in the function implementation as in:
void addStudent(struct student person)
{
return;
}

Resources