Changing a variable of a structure in C - c

Am I correct to say that if I want to change the content of a variable in a structure I have to give a pointer to the structure, using a different function to change the struction, like this:
Struct:
typedef struct data{
int row;
int column;
}data;
the var in the struct changer function:
struct data* init_maze(void) {
data information; //init information struct
data *infoPoint; //int information struct pointer
int row = 6;
int column = 10;
infoPoint->row = row; //not working but should be updating information
infoPoint->column = column; //same as above
return infoPoint;
}
But this is not working as intended. The code breaks and nothing happens. Could anyone please explain what I am doing wrong.

infoPoint should be declared as:
data* infoPoint = malloc (sizeof(data));
Then this code should work:
infoPoint->row = row; //not working but should be updating information
infoPoint->column = column; //same as above
And function init_maze doesn't need struct prefix:
data* init_maze(void)
data information;
is also unused

Another answer covers using pointers properly, but for different approach, you can pass structs around just like simple variables, so consider this version:
struct data init_maze(void) {
data information;
information.row = 6;
information.column = 10;
return information;
}
This is not as efficient as passing pointers around, but for most practical purposes and in most cases difference is irrelevant. And here size of this struct is two integers, which puts it solidly in this category.

Ask yourself first, what you want to accomplish here.
For example, you declare "data information" and you never use it. You don't even point "infoPoint" to anything before you manipulate it. Since you wrote nothing of a "SEGFAULT", I guess you are omitting some code?
Anyway. Do you want to create a new "data" struct and return it with some initial values? Then you have to either:
A) allocate some memory and return a pointer to this piece of memory on the heap (which must be allocated with malloc (or similar) and deallocated with free at some point"
B) You can take a pointer to a struct data as parameter and put your values in there.
data *init_maza(void) {
data *infoPoint = malloc(sizeof(struct data));
data->row = 6;
data->column = 10;
return data;
}
void init_maze(data *outp) {
outp->row = 6;
data->column = 10;
}
You can call B) with a pointer to a struct data on the stack or heap:
data foo;
data *bar = malloc(sizeof(struct data));
// Initialize
init_maze(&foo);
init_maze(bar);
Note the ampersand '&', the 'address-of' operator.
You can also use a pointer to pointer parameter so you still can return something else, like an error code. Used very often:
int init_maze(data **d) {
*data = malloc(sizeof(struct data));
(*data)->row = 6;
(*data)->column = 10;
return 0;
}

Your sample code is trying to modify an uninitialized pointer to a struct, so infoPoint->row = row; is an invalid operation since infoPoint is not initialized.
You could change your init function like this:
void init_maze(data *infoPoint) {
infoPoint->row = 6;
infoPoint->column = 10;
}
Then use it like this:
int main()
{
data information;
init_maze(&information);
}
data information; will allocate your struct on the stack, and you can pass a pointer to it for init_maze to do its job.

Related

Passing a struct to void* param then copying it to a void*, reconstructing gives garbage value

I am really confused with passing my struct to void pointers, I'm not sure which one can be assigned directly and which one should be memcpyed, I've tried a lot of combinations but it does not seem to work. Any help would be very appreciated!
This is my C code
struct SomeStruct {
int a;
char name[10];
};
void *randoms[10];
void transferFunction(void* data, int index) {
// This function copies data to randoms[index]
// I would like to have the whole struct's data in randoms[index]
memcpy(&randoms[index], data, sizeof(struct SomeStruct));
}
struct SomeStruct *ss = malloc(sizeof(struct SomeStruct));
ss->a = 1;
strcpy(ss->name, "abc");
transferFunction(ss, 0);
My goal is to have the randoms[index] having the struct's data as another function is going to read from it, as shown below, but I am unable to retrieve the struct data correctly, it gives me some garbage value
void readFunction() {
struct *SomeStruct ss = malloc(sizeof(struct SomeStruct));
memcpy(ss, &randoms[index], sizeof(struct SomeStruct));
printf(ss->name);
}
Does anyone knows how to solve this problem? Thank you very much!!!
You can not "copy in to a void".
A void * can contain a memory address, but does not contain any information about the size of the data at that address.
Also, it can not contain any data, only an address!
In this line:
void *randoms[10];
You create an array that can hold 10 addresses.
You never initialize this array, so it will start out all zeroes (this only works for global variables in C).
You can put the address of your structure in to the array, like so:
random[0] = (void*)ss;
However, this does not transfer any data, so if you free the original structure (ss) your data is gone, and the address in random[0] is illegal.
If you want to transfer data you need to create array of struct SomeStruct or you need to allocate another SomeStruct, store its address in random[0] then memcpy to that address.
void transferFunction(void* data, int size, int index)
{
randoms[index] = malloc(size);
if (randoms[index] != NULL) {
memcpy(randoms[index], data, size);
}
}
Your code has some problems:
struct *SomeStruct ss = ... should be struct SomeStruct *ss =.
You are not cheking the return value of malloc() (which may fail).
You are not freeing ss allocated with malloc(). You should call free() on ss.
My goal is to have the randoms[index] having the struct's data
Lev M.'s answer already answers this part.
as another function is going to read from it
Simply assign your void pointer to a SomeStruct pointer:
void readFunction(int index)
{
if (index >= 10) // Index out of range
return;
struct SomeStruct *ss = randoms[index];
printf("%s\n", ss->name);
}

C error: type name requires a specifier or qualifier

I tried to create a struct that would incude a dynamic array:
typedef struct
{
int idNode;
int* n; //pointer to the int nodes in the dynamically created array of nodes
n = calloc(MAX, sizeof(int)); //dynamic array to store the loser member of the pair
int counter = 0;
}
node;
But I get
error: type name requires a specifier or qualifier
You cannot assign a value to n in the struct declaration. You need to provide a function (something like a constructor ;-) that initializes the structure and assigns a value to its members, including n:
void init_node(node* n)
{
n->idNode = ...;
n->n = calloc(MAX, sizeof(int));
n->counter = 0;
}
Note: you still need to handle errors (e.g. calloc may fail) in the function and propagate errors to its caller.
You can't have statements or initialize an variable inside a structures.
For fix your problem
typedef struct Node {
int idNode;
int* n; //pointer to the int nodes in the dynamically created array of nodes
int counter;
} node;
int main(void)
{
node data = null;
node.n = calloc(sizeof(int), MAX);
node.idNode = 0;
node.counter = 0;
return (0)
}
Now you have initialize your struct
Starting point
I tried to create a struct that would incude a dynamic array
The problem I see in your initial snippet is you mix definition, declaration and use.
From https://www.geeksforgeeks.org/difference-between-definition-and-declaration:
Declaration of a variable is for informing to the compiler the following information: name of the variable, type of value it holds and the initial value if any it takes. i.e., declaration gives details about the properties of a variable. Whereas, Definition of a variable says where the variable gets stored.
Steps to get a basic knowledge of how to do it.
Firstly, you must know how to create a struct.
The next step is how to typedef it.
The next step is how dynamic arrays are declarated, defined, created, stored, modified or destroyed (the life cycle). Pay attention to erros may occur during the execution. The happy path of create things in C is not the only one, there are plenty of errors out there!
The next step is how to insert them into a typedef'd struct.
And the last step is use that typedef struct with a dynamic array inside it. Even you can create multiple dynamic arrays in the struct!
Note: Steps, 1, 2 and 4 may be ordered in other ways depend on the programmer
There is no shortcuts, no trial and error and, of course, you must create test programs to ensure the stuff you want and the stuff you program are the same thing.
n = calloc(MAX, sizeof(int));
int counter = 0;
You cannot use statements to execute inside of the declaration of a structure. You need to initialize n and counter inside of a function after an object of node has been defined.
E.g.:
typedef struct
{
int idNode;
int* n;
int counter;
}
node;
int main (void)
{
node a;
a.n = calloc(MAX, sizeof(int));
a.counter = 0;
}

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

How to correctly define an array of structures?

i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help
You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);
Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;
When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));
My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]

Transferring variables using structure

I want to transfer few variables using structure. Following is the sample program code. When I run this program, I get segmentation fault. I use gcc compiler.
Can anyone help me with this?
struct data{
const char * ip;
const char * address;
const char * name;
};
int fun(struct data *arg) {
//struct data *all;
const char *name = arg->name;
printf("\n My name is:%s",name);
return 1;
}
int main(int argc, char * const argv[]) {
struct data * all;
int k=0;
//data.name = argv[1];
all->name=argv[1];
k = fun(all);
printf("\n k is:%d ",k);
return 0;
}
The problem is here:
struct data * all;
all->name=argv[1];
You have not allocated memory for all. When you have an uninitialized pointer, it is pointing to random locations in the memory, which you probably won't have access to. You have two options:
Allocate on the stack:
struct data all;
all.name=argv[1];
k = fun(&all);
Allocate on the heap:
struct data *all = malloc(sizeof(*all));
if (all != NULL)
{
all->name=argv[1];
k = fun(all);
}
free(all);
The first case is good when you know that all will be needed only in the current function (and those you call). Therefore, allocating it on the stack is sufficient.
The second case is good for when you need all outside the function creating it, for example when you are returning it. Imagine a function initializing all and return it for others to use. In such a case, you can't allocate it on the stack, since it will get destroyed after the function returns.
You can read more about it in this question.
You need to allocate memory and assign it to the pointer all:
struct data * all;
int k=0;
all = malloc(struct data);
all->name=argv[1];
k = fun(all);
//...
free(all);
or use a local struct and pass its pointer to the function:
struct data all;
int k=0;
all.name=argv[1];
k = fun(&all);
all is a pointer to type struct data. You never assigned it, so it doesn't point to anything.
You need to do one of the following:
allocate all on the stack:
struct data all;
allocate all on the heap:
struct data* all = malloc(sizeof (struct data));
// don't forget to check if the allocation succeeded,
//and don't forget to free it when you're done

Resources