manipulate structs in void functions - c

I'm not very firm in using structs and currently trying to pass a struct through a void function.
The struct is defined in a shard header, as well as my void function:
/* "main.h" */
struct input{
unsigned int NO;
double RA;
double DE;
double MV;
};
void full_view_equ(struct input, struct input);
The function looks like this, it is nessecary to use two different structs. Struct EQU already contains values, OUTPUT will be uninitialized:
/* "transformations.c" */
#include "main.h"
void full_view_equ(struct input EQU, struct input OUTPUT){
OUTPUT.NO = EQU.NO;
OUTPUT.RA = -radian2degree(EQU.RA);
OUTPUT.DE = radian2degree(EQU.DE);
OUTPUT.MV = EQU.MV;
}
I'm calling the function with the two structs EQU and OUTPUT like this:
struct input EQU, OUTPUT;
full_view_equ(EQU, OUTPUT);
The problem is, that within the function, OUTPUT has the expected values. Outside the function, all entries of OUTPUT are zero instead.
I can't see what's wrong with it, before i was using arrays instead of structs and all was working fine.

You must use a pointer to the structure and pass that to the function, in your code the OUTPUT struct in the function is actually a copy of the original one and changing the copy won't change the original one.
for declaring a pointer to a struct simply use this code:
struct input *OUTPUT;
and use this header for your function:
void full_view_equ(struct input EQU, struct *input OUTPUT)
and the call to the function would be:
full_view_equ(EQU, &OUTPUT);

Function arguments are passed by value. So you need to use pointers to modify value outside the function:
void full_view_equ(struct input EQU, struct input *OUTPUT){
OUTPUT->NO = EQU.NO;
OUTPUT->RA = -radian2degree(EQU.RA);
OUTPUT->DE = radian2degree(EQU.DE);
OUTPUT->MV = EQU.MV;
}
and call it like
full_view_equ(EQU, &OUTPUT);

If you declare a function with a struct parameter, you will be sending a copy of your struct to it. Once the function returns, that copy is lost.
You can either modify your function to return the struct, in which case you have to copy it back. Alternatively, you could modify your function to take a pointer to the structs.

When you are passing array to a function, it decays to pointers in function. Because array name represent the base address. But structures are not. So pass Pointer to the structure!
Instead of this-
full_view_equ(EQU, OUTPUT);
use-
full_view_equ(EQU, &OUTPUT); // pass a pointer to a structure
and catch it by structure pointer in function, replace . by -> operator
void full_view_equ(struct input EQU, struct input *OUTPUT){
OUTPUT->NO = EQU.NO;
OUTPUT->RA = -radian2degree(EQU.RA);
OUTPUT->DE = radian2degree(EQU.DE);
OUTPUT->MV = EQU.MV;
}

When passing a variable to a function, a copy of this variable is made.
What you need here is to pass a pointer to your structure, then use
my_struct->data
instead of
my_struct.data
You will then pass a copy of the pointer to the function, but the pointed address will be your original struct, so you will be able to modify it :)

Either pass a pointer to the struct...
void full_view_equ(struct input *EQU, struct input *OUTPUT){
OUTPUT->NO = EQU->NO;
OUTPUT->RA = -radian2degree(EQU->RA);
OUTPUT->DE = radian2degree(EQU->DE);
OUTPUT->MV = EQU->MV;
}
int main(void) {
struct input a, b;
memset(&b, 0, sizeof(b));
full_view_equ(&a, &b)
}
Or return a struct from the function:
struct input full_view_equ(struct input EQU){
struct input OUTPUT;
OUTPUT.NO = EQU.NO;
OUTPUT.RA = -radian2degree(EQU.RA);
OUTPUT.DE = radian2degree(EQU.DE);
OUTPUT.MV = EQU.MV;
return OUTPUT;
}
int main(void) {
struct input a, b;
memset(&b, 0, sizeof(b));
a = full_view_equ(b);
}
In theory, a copy of the struct would need to be made in the second case, but the compiler can optimize it away.

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.

Access struct within struct in different functions

I have nested structs and I'm having trouble assigning values to the inner struct in different functions. My structs are defined as:
typedef struct {
double reading;
float readingTime;
int readingNum;
} Measurement;
typedef struct {
Measurement vref;
Measurement vout;
Measurement voutShort;
} Unit;
In the function (measureUnit()) where I declare Unit unit;I call takeMeasurement(unit) (which I simplified for clarity below) and where I try to assign values to some values in the inner Measurement struct :
takeMeasurement(Unit unit){
int readingNum = 42;
unit.vout.readingNum = readingNum;
}
When I then try to access these values in printData(Unit unit) which is called from measureUnit(),
`printf("%i", unit.vout.readingNum)`
always prints 0.
Shouldn't these values "follow" unit around through different functions?
C passes arguments by value resulting in the changes being made to unit in takeMeasurement() being applied to a copy of the argument supplied to the function. Pass the address of a Unit to the function to ensure changes are visible to the caller:
void takeMeasurement(Unit* unit){
int readingNum = 42;
unit->vout.readingNum = readingNum;
}
To invoke:
Unit u = { 0.0 };
takeMeasurement(&u);
It is also desirable to pass a pointer to a const struct to a function that only reads the values of the struct to avoid making a copy of the struct, particularly if the struct is large:
void printData(const Unit* unit)
{
printf("%i", unit->vout.readingNum);
}
You pass the struct itself to the function, which means you pass a copy of your struct to the function and modify this copy, not the original structure. You might want to pass a pointer to the struct instead:
takeMeasurement(Unit* unit){
int readingNum = 42;
unit->vout.readingNum = readingNum;
}
// call it something like that
takeMeasurement(&my_unit_struct);
// ^ this means "the address of my_unit_struct"

How do you pass a typedef struct to a function?

At the moment I'm trying
void avg(everything)
But that gives me the error:
error: subscripted value is neither array nor pointer
And when I got this error earlier today it was because I wasn't passing a 2D array to the function properly. So I figure this is the same but I can't find the correct format to pass it in.
This is my typedef:
typedef struct structure
{
char names[13][9];
int scores[13][4];
float average[13];
char letter[13];
} stuff;
And this is my typedef array:
stuff everything[13];
In the function signature, you need to specify the type, not the specific name of a variable you want to pass in. Further, if you want to pass an array, you need to pass a pointer (you should probably be passing structs by pointers anyway, otherwise a copy of the data will be made each time you call the function). Hence you function should look like:
void avg(stuff* s);
However, C arrays also have no concept of length. Hence, you should always pass in the length of the array to the function:
void avg(stuff* s, size_t len);
You'd then call this as follows:
avg(everything, 13);
Also, if the function doesn't modify the data in any way, you should signify this by specifying that the parameter is const:
void avg(const stuff* s, size_t len);
A type introduced with typedef is an alias that can be used for a real type.
For example:
typedef struct some_struct { ... } some_type_name;
Now you can use some_type_name instead of struct some_struct.
So when declaring a function which takes a structure of this "type" you use the type like any other type:
void some_function(some_type_name var) { ... }
In some_function as defined above, you can use var like a normal structure variable.
To define a function taking an array (or a pointer) to this type, that's equally simple:
void some_function(some_type_name *pointer) { ... }

Pass struct by reference in C

Is this code correct? It runs as expected, but is this code correctly using the pointers and dot notation for the struct?
struct someStruct {
unsigned int total;
};
int test(struct someStruct* state) {
state->total = 4;
}
int main () {
struct someStruct s;
s.total = 5;
test(&s);
printf("\ns.total = %d\n", s.total);
}
Your use of pointer and dot notation is good. The compiler should give you errors and/or warnings if there was a problem.
Here is a copy of your code with some additional notes and things to think about so far as the use of structs and pointers and functions and scope of variables.
Note: A code writing difference in the source example below is I put a space after the struct name and before the asterisk in the function definition/declaration as in struct someStruct *p1; and the OP put a space after the asterisk as in struct someStruct* p1;. There is no difference to the compiler, just a readability and habit difference for the programmer. I prefer putting the asterisk next to the variable name to make clear the asterisk changes the variable name it is next to. This is especially important if I have more than one variable in a declaration or definition. Writing struct someStruct *p1, *p2, var1; will create two pointers, p1 and p2, and a variable, var1. Writing struct someStruct* p1, p2, var1; will create single pointer, p1 and two variables p2 and var1
// Define the new variable type which is a struct.
// This definition must be visible to any function that is accessing the
// members of a variable of this type.
struct someStruct {
unsigned int total;
};
/*
* Modifies the struct that exists in the calling function.
* Function test() takes a pointer to a struct someStruct variable
* so that any modifications to the variable made in the function test()
* will be to the variable pointed to.
* A pointer contains the address of a variable and is not the variable iteself.
* This allows the function test() to modify the variable provided by the
* caller of test() rather than a local copy.
*/
int test(struct someStruct *state) {
state->total = 4;
return 0;
}
/*
* Modifies the local copy of the struct, the original
* in the calling function is not modified.
* The C compiler will make a copy of the variable provided by the
* caller of function test2() and so any changes that test2() makes
* to the argument will be discarded since test2() is working with a
* copy of the caller's variable and not the actual variable.
*/
int test2(struct someStruct state) {
state.total = 8;
return 0;
}
/*
* Make a local copy of the argument then modify the local copy.
* Until the assignment of the local copy to the argument is made,
* the changes to the local copy are not made to the argument.
* To make any changes made to the local copy in the argument,
* you need to assign the local copy to the argument.
*/
int test3(struct someStruct *state) {
struct someStruct stateCopy;
stateCopy = *state; // make a local copy of the struct
stateCopy.total = 12; // modify the local copy of the struct
*state = stateCopy; /* assign the local copy back to the original in the
calling function. Assigning by dereferencing pointer. */
return 0;
}
int main () {
struct someStruct s;
/* Set the value then call a function that will change the value. */
s.total = 5;
test(&s);
printf("after test(): s.total = %d\n", s.total);
/*
* Set the value then call a function that will change its local copy
* but not this one.
*/
s.total = 5;
test2(s);
printf("after test2(): s.total = %d\n", s.total);
/*
* Call a function that will make a copy, change the copy,
then put the copy into this one.
*/
test3(&s);
printf("after test3(): s.total = %d\n", s.total);
return 0;
}
That's correct usage of the struct. There are questions about your return values.
Also, because you are printfing a unsigned int, you should use %u instead of %d.
Yes, that's right. It makes a struct s, sets its total to 5, passes a pointer to it to a function that uses the pointer to set the total to 4, then prints it out. -> is for members of pointers to structs and . is for members of structs. Just like you used them.
The return values are different though. test should probably be void, and main needs a return 0 at its end.
Yep. It's correct. If it wasn't (from the . / -> point of view), your compiler would yell.
Yes, its correct usage of structures. You can also use
typedef struct someStruct {
unsigned int total;
} someStruct;
Then you won't have to write struct someStruct s; again and again but can use someStruct s; then.

New to C and C Structures -- How to take a struct as a parameter in a function

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

Resources