Access struct within struct in different functions - c

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"

Related

How to write after the end of the already initialized struct?

I have a struct initialized on a stack, and i want to write data in memory right after the struct and make a pointer inside a struct point to that data.
I know it is achievable on the stack/heap with uninitialized structure using malloc(sizeof(struct) + additional size) or alloca(). but can i perform initialization of a data after the struct is already initialized on the stack? and can i perform this initialization inside a initializator function?
Simple example:
struct TEST {
wchar_t* itest;
};
void init_struct(struct TEST* test) {
// point to the end of the struct
char* walk_ptr = (char*)test + sizeof(test);
test->itest = (wchar_t*)walk_ptr;
// initialize data after the struct
...
}
int main(void) {
struct TEST test;
init_struct(&test);
return 0;
}
You could do this by embedding the structure inside another structure to reserve memory for the extra data:
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test);
…
}
However, the code in init_struct adds an incorrect size, sizeof(test), to the pointer. You likely wanted to add sizeof (struct Test), or, equivalently, sizeof *test, since you want to get past the struct TEST that test points to, not past a struct TEST * that test is.
However, even adding the correct size of the structure would not guarantee strictly conforming C code, since C implementations may insert padding between structure members. Properly we would add the offset of the data member. To do that, we nwould eed to give the structure a tag and then either make the structure definition visible to init_struct or pass the offset to init_struct. However, it is easier just to pass the address of the extra data:
void init_struct(struct TEST *test, wchar_t *data)
{
test->itest = data;
}
int main(void)
{
struct { struct TEST test; wchar_t data[NumberOfElements]; } S;
init_struct(&S.test, S.data);
…
}
Of course, a pointer can point anywhere, and there is no apparent reason the data should be immediate after the structure, so we can disconnect them:
int main(void)
{
struct TEST test;
wchar_t data[NumberOfElements];
init_struct(&test, data);
…
}

How to pass local structures to functions?

The following link says that structs defined in main don't have the scope to be called by functions because they are local so you should define your structs globally. However with variables, it's preferred to declare variables locally and pass to functions with pointers instead of declaring global variables.
Is there a way in pure C using pointers etc to pass a struct defined in main to a function? If you don't mind, please use the example program to demonstrate the method. Thanks.
where to declare structures, inside main() or outside main()?
This code works but is not what I want. I want to define the structure within main. Is this possible?
#include <stdio.h>
#include <SDL2/SDL.h>
void function();
struct hexColour
{
Uint32 red;
}hc;
int main(void)
{
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
void function(struct hexColour hc)
{
printf("red is %x\n", hc.red);
}
What I want is:
int main(void)
{
struct hexColour
{
Uint32 red;
}hc;
hc.red = 0xFFFF0000;
function(hc);
return 0;
}
First of all you should really use proper prototypes that matched the function definitions.
Secondly, your example do pass a structure into the local variable hc in the function.
When function is running there are two distinct and separate structures in memory: The one in the main function, and the local in the function function.
To cover my bases, here are two answers for two other question that maybe is asked:
You want to define the structure itself inside the main function, and then be able to use it in other functions.
Something like
int main(void)
{
struct hexColor
{
uint32_t white;
// Other members omitted
};
struct hexColour hc;
hc.white = 0xff;
func(hc); // Assume declaration exist
}
void func(struct hexColour my_colour)
{
printf("White is %u\n", my_colour.white);
}
This is not possible. The structure hexColour is defined inside the main function only. No other function can use that structure. It doesn't matter if you pass a pointer or not, the structure hexColour still will only exist inside the main function only.
Emulate pass-by-reference by passing a pointer to a structure object. Like
struct hexColor
{
uint32_t white;
// Other members omitted
};
int main(void)
{
struct hexColour hc;
hc.white = 0xff;
// Assume declaration of function exists
func(&hc); // Emulate pass-by-reference by passing a pointer to a variable
}
void func(struct hexColour *colourPointer)
{
colourPointer->white = 0x00;
}
This is possible, because then the structure hexColour exists outside the main function, in the global scope. All functions declared and defined after the structure definition may use the structure and its members.
If you pass by value a copy is made (expensive, modifications are not reflected outside). If you want to pass a pointer to a struct just go with, but this doesn't mean you are passing a struct by reference (C doesn't have references), you are passing a pointer to a struct by value instead.
void function(struct hexColour* hc) {
printf("red is %x", hc->red);
}
int main() {
...
functon(&hc);
...
}
See:
Signature of the function changes from struct hexColor to struct hexColor* so that you are passing a pointer (by value)
To access field of the struct when dealing with pointers you use -> instead that .
You need to take the address to the struct when invoking the function, function(hc) becomes function(&hc)
Now since you are passing the address the the struct any modification is done to the real value.
You seem to have understood your linked question and its answers incompletely. You write,
The following link says that structs defined in main don't have the
scope to be called by functions because they are local so you should
define your structs globally.
The ambiguity here is between struct types, such as your struct hexColour, and objects having those types, such as your hc. Both struct types and struct objects should be declared so that they are in scope at all the places where they are needed, but that plays out differently for these two different kinds of entities and in various different situations.
However with variables, it's preferred to declare variables locally
and pass by reference instead of declaring global variables.
It is usually best to use block-scope variables instead of file-scope variables, yes, but C has only pass by value, not pass by reference. There are plenty of circumstances where it is advantageous to pass pointers (by value) instead of the objects to which they point, and this is close to pass by reference, but there is certainly no rule or general practice that passing pointers is universally better than passing the objects to which they point.
Is there
a way in pure C using pointers etc to pass a local struct to a
function?
Both the caller and the callee have to agree about the type of each argument, and there are many ways to achieve this. But there are some conventions that have grown up along with C for how to approach problems such as these in an effective way. Large among them is this:
Any function and any non-builtin type that is to be used in multiple translation units should be declared in a header file, and that header included in every translation unit that needs it.
That's a generalization of the rule you couched in terms of "global" definitions. Example:
colour.h
#ifndef COLOUR_H
#define COLOUR_H
struct hexColour {
Uint32 white;
Uint32 black;
Uint32 red;
Uint32 pink;
Uint32 grey;
}; // Note that only the type is declared here, not any objects
void function(struct hexColour hc);
#endif
Note that the declaration of type struct hexColour appears before the declaration of function function that has a parameter of that type.
You can then use those types and functions with appropriate locality, for example:
main.c:
#include "colour.h"
int main(void) {
struct hexColour hc = {
.white = 0xFFFFFFFF, .black = 0xFF000000, .red = 0xFFFF0000,
.pink = 0xFFFF9999, .grey = 0xFFA0A0A0 };
function(hc);
return 0;
}
void function(struct hexColour hc) {
printf("red is %x\n", hc.red);
}
Note that the declaration of function that forms part of its definition here matches the declaration in the header. That definition function() could as easily be defined in a different source file, instead, as long as the caller has the header file to tell it how that function is declared. You can #include coulour.h into as many different source files as needed.
Do note, however, that in this case, the struct is passed by value. That's well-defined and perfectly acceptable, but inasmuch as the function receives only a copy, it cannot effect changes to the caller's original copy. If you wanted the function to be able to do that, then you would need to pass a pointer to the struct (by value) instead of the struct itself:
void function(struct hexColour *hc) {
// ...
}
int main(void) {
// ...
function(&hc);
// ...
}
You can take a locally-defined struct and pass it to another function:
void f1(struct s);
int main()
{
struct s s1;
f1(s1);
}
You can take a locally-defined struct and pass a pointer to it to another function:
void f2(struct s *);
int main()
{
struct s s2;
f2(&s2);
}
You can return a locally-defined struct:
struct s f3()
{
struct s ret;
/* ... */
return ret;
}
You can not return a pointer to a locally-defined struct:
struct s *f4()
{
struct s ret;
/* ... */
return &ret; /* WRONG */
}
If you declare a struct within a function, it is not a global variable, so you can not refer to it in another function to which you did not pass the structure or a pointer:
void f5();
int main()
{
struct s s1;
f5();
}
void f5()
{
int x = s1.field; /* WRONG */
}
Finally, if you declare the struct type itself inside a function, you end up with a struct which you can't properly refer to elsewhere:
void f1(struct s);
int main()
{
struct s { int a, b; } s1;
f1(s1);
}
void f1(struct s arg) /* error: this struct s might not be the same as the previous one */
{
int x = arg.b; /* error: compiler might not know that struct s contains a and b */
}
Looked at the previous answers. Suggest you wrap your mind around the 'C' difference between a declaration and a definition. Note that earlier versions of 'C' would NOT allow passing a copy of a structure on the stack, only a pointer to a struct..

Passing a struct as an argument

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.

manipulate structs in void functions

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.

Structure returning function

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.

Resources