Pass struct by reference in C - 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.

Related

Using a pointer to struct returned from a function

I have a function which clones members of a struct and returns a struct (NOT pointer). This newly created object is short lived.
struct my_struct {
int a;
int b;
};
inline struct my_struct my_struct_clone(struct my_struct src, int members){
struct my_struct copy = {0};
//... Do copy based on args
return copy;
}
I cannot return a pointer as it would be pointing to deallocated memory. How can I pass the return value of the clone function as a pointer to a second function? Similar to the following, but without using an intermediate placeholder.
void do_sth(struct my_struct const *p);
struct my_struct val = my_struct_clone(&other, 123);
do_sth(&val);
The following fails (lvalue required as unary ‘&’ operand):
do_sth(&(my_struct_clone(&other, 123)));
But it is possible to declare a struct inline
do_sth(&(struct my_struct){.a = 1, .b = 2});
To address some of the comments about using an intermediate. The question is about avoiding the creation of one, and not "I can't use one because...". I recently encountered a coding construct where I thought I could but discovered I couldn't, hence the question. Also, passing in an already allocated instance to the clone function still requires an intermediate. I would prefer to not clutter the function header with variable declarations that are short lived like this.
The value returned by the function is an rvalue,
which means that its address can't be taken.
But compound literals are lvalues which means their address can be taken.
You need the temporary variable to be able to pass the result of the cloning function as a pointer.
I would personnaly do something like:
inline void my_struct_clone(const struct my_struct src, struct my_struct *srcCopy, int members){
//... Do copy based on args
srcCopy->a = src.a;
srcCopy->b = src.b;
}
So you would call and declare the clone as such:
struct my_struct strClone;
my_struct_clone(str, &strClone, 123);
do_sth(strClone); // Call to strClone

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.

better usage of structures in embedded field

I'm bit new to c programming and i want to learn and use the structure facility in C programming.
I'm working in the embedded programming field of 8bit controllers.
I have a situation in which
objective:
To set time and date or more things.
To get time and date or more things.
Problem: I have two source files main.c and set_get.c i have a struct
varaible in main.
Aim : to set and get rtcc values from registers in pic18 series controllers and to create a test platform.
main()
{
struct data
{
unsigned char hour=10;
unsigned char date=20;
} entry;
entry=set_time_date(entry);
entry=get_time_date();
while(1);
}
and in set_get.c
i have two functions
//here struct parameter will be the input from main.c
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
struct set_time_date(struct x)
{
struct data p1;
p1.hour=x.hour;
p1.date=x.date;
//do set hour register with p.hour value
//do set date register with p.date value
return(p1);
}
struct get_time_date(void)
{
struct data p1;
p1.hour= do read from hour register;
p1.date= do read from day register;
return(p1);
}
I would like to have your inputs on this and correct me if i have made any mistakes in the following pattern.I have done in this method so as to reduce global structs.
And im keenly waiting your review on this piece of code.Correct me if im wrong
Regards
Arookie
Note, there is a rich library of time functions included in C89, C99, etc.
time_t time (time_t *Current_Calendar_Time);
clock_t clock (void);
char *ctime (const time_t *Calendar_Time);
Just to name a few. But in keeping with the theme of what you have already done...
First, This code segment will not compile. Assignments cannot be made inside the struct definition:
struct data
{
unsigned char hour=10;
unsigned char date=20;
};
However, once the struct is defined, you can make assignments to each individual member (see examples in code example below) Or you can make a block assignment, like this:
//Note, I am using a typedef variation of your original for illustration:
typedef struct data{
unsigned char hour;
unsigned char date;
} data;
//make block assignment here:
// hour date
struct data a = {0x34, 0xA5};
Next, passing a pointer to struct is sometimes better than passing the struct itself. i.e. when volume of data is large, passing address (~4bytes) is preferable to passing possibly hundreds of bytes. (For the size of your struct, it is really not a concern) My examples will use pointers:
For readability, create a type:
//you originally used unsigned char for member types. I changed it to
//accommodate puctuation,as often, timestrings and datestrings use
//puncutation such as : or /
//The unsigned version is below this one...
#define TIME_LEN 20
#define DATE_LEN 20
typedef struct {
char hour[TIME_LEN];
char date[DATE_LEN];
} DATA;
//use DATA to create the other instances you need:
DATA entry, *pEntry;
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(void);
//In main, initialize pointer to struct this way:
int main(void)
{
pEntry = &entry;//initialize pointer pEntry to address of entry
sprintf(pEntry->date , "%s", "12/23/2014");
sprintf(pEntry->hour , "%s", "10:12:13");
set_time_date(pEntry);
pEntry = get_time_date();
return 0;
}
void set_time_date(DATA *x)
{
sprintf(pEntry->date, "%s", x->date);
sprintf(pEntry->hour, "%s", x->hour);
}
DATA * get_time_date(void)
{
sprintf(pEntry->date, "%s", "01/23/2014");
sprintf(pEntry->hour, "%s", "10:10:00");
return pEntry;
}
using unsigned char
In this section, changes have been made to accommodate minimization of global struct. By creating a typedef of the struct, say in a header file, you can then simply use DATA * where needed to create a local instance of the struct, and pass it as an argument...
//Your function prototypes become:
void set_time_date(DATA *x); //no need to return time in set function
DATA * get_time_date(DATA *x); //Edited to include argument
//In main, initialize pointer to struct this way:
int main(void)
{
//Create local instance of DATA:
DATA entry={0}, *pEntry;
pEntry = &entry;//initialize pointer pEntry to address of entry
pEntry->date = 0x12;
pEntry->hour = 0x23;
set_time_date(pEntry);
pEntry = get_time_date(pEntry);
//print results showing values of both pEntry and entry
printf("pEntry->date: 0x%x\n", pEntry->date);
printf("entry.date: 0x%x\n", entry.date);
printf("pEntry->hour: 0x%x\n", pEntry->hour);
printf("entry.hour: 0x%x\n", entry.hour);
//After the assignment: "pEntry = &entry;" (above)
//pEntry is pointing to the the same location
//in memory as the start of entry. (this is the reason for that assignment)
//Every subsequent assignment you make to pEntry, is also being
//written to entry, without explicitly having to
//write: entry.date = 0x23 etc. (indeed, it is the same location
//in memory you are writing to)
return 0;
}
void set_time_date(DATA *x)
{
x->date = 0xBC;
x->hour = 0x45;
}
DATA * get_time_date(DATA *pX)
{
//Commented following two lines, passed in as argument:
//DATA x, *pX; //now passed in as argument
//pX = &x;//initialize pointer pX to address of x
pX->date = 0x23;
pX->hour = 0x34;
return pX;
}
Produces following output

pointer to a structure within a structure in C

I have a structure (let's call it structure1) which holds a pointer to another structure (structure2), this way.
typedef struct structure{
structure2 *pointer
}structure;
structure structVariable;
structVariable.pointer = functionThatReturnsAPointerToStructure2Variable();
The thing is, as the program changes context (for example, when calling functions), the return value of the following code changes
structVariable.pointer->someAttribute
Any idea of why this might be happening? If you need more info please ask. Thanks!
MORE INFO
This is the real-deal
structure would be this
typedef struct CPU{
int variableCounter;
int instructionPointer;
char *currentInstruction;
t_list *dataDictionary_list;
u_int32_t currentContext;
PCB *assignedPCB;
CPU_STATUS status;
}CPU;
And this is how I assign the pointer (PCB *pointer)
PCB *pcb_createFromScript(const char *script){
t_medatada_program *metadata = metadatada_desde_literal(script);
PCB *pcb = malloc(sizeof(PCB));
pcb->instructionCount = metadata->instrucciones_size;
pcb->tagCount = metadata->cantidad_de_etiquetas;
pcb->functionCount = metadata->cantidad_de_funciones;
int codeSegmentSize = strlen(script);
int tagIndexSize = 0;
if(metadata->etiquetas != 0){
tagIndexSize = strlen(metadata->etiquetas);
}
int instructionIndexSize = metadata->instrucciones_size * sizeof(t_intructions);
pcb_getSegments(pcb,1024,codeSegmentSize,tagIndexSize,instructionIndexSize);
pcb->currentContext = pcb->stackSegment;
pcb->variableCounter = 0;
memory_write(pcb->codeSegment,0,codeSegmentSize,script);
memory_write(pcb->tagIndexSegment,0,tagIndexSize,metadata->etiquetas);
memory_write(pcb->instructionIndexSegment,0,instructionIndexSize,(void *)metadata->instrucciones_serializado);
pcb->uniqueId = (int) random();
return pcb;
}
And then I assign it this way (myCPU is global), that's why I call it inside cpu_getPCB without passing it as a parameter
cpu_getPCB(*dummyPCB);
void cpu_getPCB(PCB myPCB){
myCPU.currentContext = myPCB.currentContext;
myCPU.assignedPCB = &myPCB;
}
Here is some speculation.
If you are modifying the object that structVariable.pointer points to in some function, then when you try to read structVariable.pointer->someAttribute, that value will change to reflect to modification to the object.
Another possibility, as the other answer mentioned, is that structVariable.pointer is pointing to local memory (stack memory for a function) which can easily be overwritten on a new function call. That can be corrected by using malloc to do heap allocation instead of stack allocation.
Here is the first and most obvious issue. You are taking the address of a parameter and assigning it to myCPU.assignedPCB.
Since C is pass-by-value, you have copied it instead of capturing the original. Moreover, the parameter has the same lifetime as a local variable, and will go away when the function returns.
void cpu_getPCB(PCB myPCB){
myCPU.currentContext = myPCB.currentContext;
myCPU.assignedPCB = &myPCB;
}
You can fix it by passing a pointer instead, since you are in C and do not have access to the reference type.
void cpu_getPCB(PCB* myPCB){
myCPU.currentContext = myPCB->currentContext;
myCPU.assignedPCB = myPCB;
}
The "structure2 *pointer" will be pointing at a piece of memory that will disappear when you change context. Allocate the Structure2 variable and free it when it's no longer needed

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