Suppose there exists a function which returns a message
say of the following format:
struct message
{
void* data;
}msgG;
Which would be the best way to extract the data (i.e. Get the message accessible to fun1 in the code):
1- using a global variable
2- Using double pointers(pointer to a pointer)
//Note: msgG is the global variable
void fun2(struct message **ptr)
{
**ptr = msgCreate(); // msgCreate returns a type struct message;
msgG = msgCreate();
}
void fun1()
{
....
.....
struct message *ptr;
ptr = malloc(sizeof(struct message));
fun2(&ptr);
...
}
Now we have the message stored in msgG and ptr ?
Which is the better one? Using global variable or accessing the pointer since one is allocated in the heap and the other in the bss(not sure of this)??
Is there any other way to deal with this kind of situation?
Don't use a global variable. What you're trying to do can be done this way:
void fun2(struct message *ptr)
{
*ptr = msgCreate();
}
void fun1()
{
struct message *m = malloc(sizeof *m);
if (m == NULL) {
/* error handling */
}
fun2(m);
}
If struct message is big, consider not having a function returning such a struct. In most of the cases, it is more efficient to return a pointer to some memory than to return a big automatic variable from a function.
It's good practise to avoid globals.
Note: if you are trying to code object-oriented in C, have a look to this documentation ooc.pdf
It can be as simple as this:
struct message
{
void* data;
} msgG;
void fun2(struct message the_msg)
{
/* access the_msg.data */
}
void fun1()
{
struct message *ptr;
ptr = malloc(sizeof(struct message));
ptr->data = ... /* initialize it to something */
fun2(*ptr);
}
But this way, fun2 won't be able to manipulate the_msg, because it's passed a copy of the structure by-value. It will be able to manipulate the stuff pointed to by the data pointer inside the_msg, because that's a pointer.
If you want to manipulate the contents of the_msg itself, such as retarget the data pointer, fun2 should accept a pointer to message (a double pointer is unnecessary for this).
And a global variable is almost always a bad solution. Don't use it.
Related
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);
}
Lets say I have this structure
typedef struct Stack
{
int firstPlayerScore;
int secondPlayerScore;
int gamesCount;
}Stack;
and this function to ini the values:
void initStack(Stack *g)
{
g->firstPlayerScore = 0;
g->secondPlayerScore = 0;
g->gamesCount = 0;
}
The problem is here, I need to be able to reset other values, but keep g.gamescount and add +1 each time gameStart function runs. Its probably a simple solution ,but I am starting to lose my mind, thank you.
void gameStart(int choice) {
Stack g;
initStack(&g);
++g.gamesCount; // this works only once, then is reset again to 0.
{
// do stuff
}
}
Cant do differently, since I believe Structure need to be inicialized. Maybe it is possible to inicialize only once somehow?
P.S I cant use global variables
Pass a pointer to the state to your function:
void gameStart(Stack *g, int choice) {
++g.gamesCount; // this works only once, then is reset again to 0.
{
// do stuff
}
}
Then inside main():
int main() {
Stack g;
initStack(&g);
gameStart(&g, 49);
}
You need to allocate memory for the struct Stack variable g. You do not need global variables, what you need is to just while declaring g you need to call malloc function to allocate memory of the size of the struct type. It looks like this:
void gameStart(int choice) {
Stack *g = (Stack *) malloc(sizeof(Stack));
initStack(g);
++g->gamesCount; // this works only once, then is reset again to 0.
{
// do stuff
}
}
Malloc returns you void *, so it is better to typecast to Stack *. Also, you need to create Stack *, as it is a struct type and requires pointer tpye.
Hope this will help you.
I have a struct, for example:
typedef struct{
int num;
} S, *Sp;
now, what I want to do is create a pointer of this type (without allocating memory), pass is to a function as a parameter and inside the function allocate the memory etc.
something like
void foo(Sp p){
p = malloc.....
p->num = ....
}
and then in main do something like this:
Sp new = NULL;
foo(new);
but after foo is done 'new' remains NULL, like it was never allocated. I feel like I'm doing something wrong here.
(this is a small part of a HW assignment, and I can't change the function definition.)
You should understand that in C, arguments are passed by value (not by reference). So when a function changes a formal argument, no change happens in the caller function. Hence, pass the address of your pointer.
void foo(S**pp) {
*pp = malloc(sizeof(S));
if (!*pp) { perror("malloc"); exit(EXIT_FAILURE); };
// fill *pp
}
and call
S* ptr;
foo (&ptr);
Actually, it is much more common to have the building function return a pointer:
S* make_s(void) {
S* p = malloc(sizeof(S));
if (!p) { perror("malloc"); exit(EXIT_FAILURE); };
// fill p
return p;
}
Then call
S* ptr = make_s ();
The important thing is to document a convention about who should free the pointer. If the allocated structure contains internal pointer, make a routine delete_s which frees the internal pointer and the whole pointed structure.
BTW, avoid using typedef for pointers (like your Sp), you really want to know what is a pointer at a glance. Don't use new or delete in public C function names, because you may want later your header files to be included by C++ code.
void foo(Sp *p){
*p = malloc.....
*p->num = ....
}
then
Sp new = NULL;
foo(&new);
if you want to keep the prototype of the function as void foo(Sp p), you have to go:
Sp new = (Sp) malloc(sizeof(S));
foo(new);
If you can't change the function declaration, then you need to allocate the memory for the structure in main.
void foo(Sp ptr){
ptr->num = ....
}
In main:
Sp itemPtr = malloc...;
foo( itemPtr );
Or this in main:
S item;
foo( &item );
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
I'm trying to create a stack in C for fun, and came up with the idea of using struct to represent the stack. Then I add function pointers to the struct for push() and pop() operations.
So far all is good it seems, but, for the implementation of the push() and pop() functions I need to refer to *this somehow. How can that (can it?) be done?
This is my struct
struct Stack {
int *data;
int current_size;
int max_size;
int (*push)(int);
int (*pop)();
};
And as an example here's push
int push(int val) {
if(current_size == max_size -1)
return 0;
data[current_size] = val;
current_size++;
return 1;
}
As you can imagine, the compiler has no idea what current_size is, as it would expect something like stack->current_size.
Is this possible to overcome somehow?
There's no implicit this in C. Make it explicit:
int push(Stack* self, int val) {
if(self->current_size == self->max_size - 1)
return 0;
self->data[self->current_size] = val;
(self->current_size)++;
return 1;
}
You will of course have to pass the pointer to the struct into every call to push and similar methods.
This is essentially what the C++ compiler is doing for you when you define Stack as a class and push et al as methods.
The typical approach in C is to have functions expect this as the first parameter.
int push(Stack *self, int val)
{
if (self->current_size == self->max_size -1) return 0;
self->data[self->current_size++] = val;
return 1;
}
This has the added benefit that, unless you need polymorphism, you don't need to put the functions in the stack, because you could just call push(stack, 10) instead of stack->push(stack,10).
C doesn't work like that. It's not an object oriented language. Functions that manipulate data structures need to take a pointer to the structure as an argument.
In header file you can declare static this variable
static struct Stack *this;
And then in push method you can use this variable
static int push(int val) {
if(this->current_size == this->max_size - 1)
return 0;
this->data[this->current_size] = val;
(this->current_size)++;
return 1;
}
The caveat is you have to manually set this variable through some method before you want to invoke other methods, eg:
struct Stack {
struct Stack (*_this)(struct Stack *); // <-- we create this method
int *data;
int current_size;
int max_size;
int (*push)(int);
int (*pop)();
};
And then we can implement _this method as
static struct Stack *_this(struct Stack *that)
{
retrun this = that;
}
The example:
struct Stack stack1, stack2;
... some initialization ...
stack1->_this(&stack1)->push(0);
stack1->push(1);
stack1->push(2);
stack2->_this(&stack2);
stack2->push(10);
stack2->push(20);
Your function pointers aren't methods so they don't have any information about the calling object. The only way to do what you want is to either pass in a pointer to the object, or make that pointer global (the latter is not recommended).
Obviously you can have a Stack * member in the struct and then just initialize it with the address of the struct before you use the function pointers. Then make the Stack * a parameter on the function pointers.
Since your are going to have only one Stack structure (that you named stack, apparently), you could define it as a global variable. This would allow pop/push to refer to the stack variable directly.
You would do something like:
stack.current_size += 4;
or use the -> operator if you decide to declare stack as a memory pointer to Stack.