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.
Related
I have a array of structs in the main function and I would like to save data of few structs. I'm using a function that receive the wanted data and put it into struct that is defined into the function.
At the end of the process I return the address of this struct.
But if I call to this function few times ,it always defines the same address of the struct so I am losing a data of the previous call.
#include<stdio.h>
struct data {
int day;
};
struct data* Dates(int val);
int main() {
struct data* Dates1[3];
int array[] = { 12, 15, 2021 };
for (int i = 0; i < 3; i++) {
Dates1[i] = Dates(array[i]);
}
}
struct data* Dates(int val) {
struct data Date;
Date.day = val;
return &Date; ///AFTER EVERY CALL TO THIS FUNCTION IT RETURN THE SAME ADDRESS!!!
}
When you call a function, it creates a stack frame. Local variables to that function are allocated within that stack frame. When the function exits, the stack frame is "destroyed". That memory can be reused.
You're seeing this behavior because each time you call the function in your loop, it reuses the same memory space.
You cannot rely on the validity of an address to a variable allocated on the stack outside of the current function call. If you need a value to live on after the function call, you need to dynamically allocate it - typically with malloc. Just don't forget to free that memory when you're done with it.
You have to write you function as something like this:
struct data* Date = (struct data*) malloc(sizeof(struct data))
Date->day = val;
return Date;
Afterwards you have to call free() on the pointer when it is no longer used. (if not this is called a memory leak)
When you are confused keep in mind the simple rule that you can only return pointers up to that call level where the variable pointing too was created.
If you want to learn why this is, you should read up on what a call stack is and how stack variables work.
If you don't want to use malloc, an alternative is have the function take in a pointer to the uninitialized value, void Dates(struct data *, int);, then the caller is responsible for the memory.
#include <stdio.h>
#include <assert.h>
struct data {
int day;
};
static void Dates(struct data *const data, const int val) {
assert(data); /* Defensive debug. */
data->day = val;
}
int main(void) {
int array[] = { 12, 15, 2021 };
struct data dates1[sizeof array / sizeof *array];
for(int i = 0; i < sizeof dates1 / sizeof *dates1; i++)
{
Dates(dates1 + i, array[i]);
printf("%d: %d\n", i, dates1[i].day);
}
}
This can be better suited for when one wants a memory-allocation-agnostic function; in this example, I've reserved memory on the heap instead of dynamically.
I have to initialize tCoworking coworking by implementing init_coworking function that is declared at the end.
/* Constants *********************************************************/
#define nWorkSpaces 50
#define unlimited 2000
/* Types *************************************************************/
typedef enum {tableFlex, tableFix, officeFix} rate;
typedef char string[55];
typedef struct {
int reservationId;
float monthPayment;
} tContractAnnex;
typedef struct {
int id;
string name;
int discount;
} tPartner;
typedef struct {
int id;
float surface;
rate rateType;
} tWorkspace;
typedef struct {
int partnerId;
int month;
int year;
tContractAnnex annex;
} tContract;
typedef struct {
tWorkspace workSpace[nWorkSpaces];
tContract contract[unlimited];
tPartner partner[unlimited];
} tCoworking;
/* Function declaration */
void init_coworking(tCoworking *coworking);
As you can see the problem I have is that tCoworking is a nested struct with array of stucts as data types..
So far I'm doing this in order to initialize it but it must be a better way to do it.
void init_coworking(tCoworking *coworking){
coworking = malloc(sizeof(tCoworking));
coworking->partner[0].id = 0;
coworking->partner[0].discount = 0;
strcpy(coworking->partner[0].name, "");
coworking->workSpace[0].id = 0;
coworking->workSpace[0].rateType = 0;
coworking->workSpace[0].surface = 0;
coworking->contract[0].partnerId = 0;
coworking->contract[0].year = 0;
coworking->contract[0].month = 0;
coworking->contract[0].annex.monthPayment = 0;
coworking->contract[0].annex.reservationId = 0;
}
void init_coworking(tCoworking *coworking) {
coworking && memset( coworking, 0, sizeof( tCoworking ) );
}
memset initializes a block of memory - of specifiable length - to a single byte value. Your example indicates that you desire zero-initialization of the entire object, so memset serves this purpose well.
NULL-check your input argument.
I recommend you not malloc or calloc in your function because your function signature implies that the caller is the owner of the tCoworking. If you malloc within your init_coworking() function, then you'll have created a new heap-allocated instance of a tCoworking with no clear ownership. You can try keep track of newly-allocated objects in some type of container, but that's going far beyond the scope of your question -- keep it simple.
The simplest way is to use calloc. Like malloc it allocates memory for you but it also sets all the memory to zero.
However - more important is that your current function doesn't make sense. The memory you allocate is simply lost. The caller of init_coworking will never get the allocated and initialized memory.
Either you should:
Not do any malloc(or calloc)
or
Return the malloced pointer.
Since the prototype suggest that you get a tCoworking pointer, the most likely thing is that it's already allocated (in some way), i.e. you want option 1.
So just do:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(coworking, 0, sizeof(tCoworking));
}
In case you only want the first array member set to zero (like your code indicates) you may get a little performance improvement by:
void init_coworking(tCoworking *coworking){ // NO malloc
memset(&coworking->partner[0], 0, sizeof(coworking->partner[0]));
... similar for the other arrays ...
}
but I doubt that's worth the trouble...
is there any way to move pointer, which is initialized in main() function, to first executable function and have it accessible in whole program?
Here's the code:
main function, where is pointer d initialized:
void main(){
int x;
deque *d;
d=(deque*)malloc(sizeof(deque));
initDeque(d);
and I want to move the pointer into function called initDeque()
void initDeque(deque *d){ //Create new deque
d->front=NULL;
d->rear=NULL;
}
Is it possible to move it?
If by "move the pointer" you mean that you want to move the variable declaration, then you can do that but it will become a local variable only accesible inside that function. Clearly not what you want.
You need to make it global, that will make it accessible from all scopes. Note that global variables are considered ugly and increase the risk of errors and generally make the code less clear.
With a global pointer it would look like this:
deque *d;
void initDeque(void)
{
d = malloc(sizeof *d);
d->front = d->rear = NULL;
}
Note that you shouldn't cast the return value of malloc() in C.
Also note that nobody would have a global variable named using a single lower-case letter. It's way to easy to confuse it with a local variable, so you should at least make the name more obvious, e.g. something like
deque *theDeque;
Create a static structure to store all you want share.
Create a function to allocate your deque. I don't know the size of deque perhaps you can take it on the stack instead of the heap.
static struct {
deque d*;
} _G;
void main(){
int x;
_G.d = deque_new();
}
deque *deque_new(void){
deque *d;
d = malloc(sizeof(deque));
d->front=NULL;
d->rear=NULL;
return d;
}
or with the stack
static struct {
deque d;
} _G;
void main(){
int x;
deque_init(&_G.d);
}
deque *deque_init(deque *d){
memset(d, 0, sizeof(*deque));
return d;
}
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.
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.