Error in Static Global Variable (C) - c

I have around 14 void functions that contains processes needed in order for my program to work
and all the 14 functions share the same variables so I thought of making them into static Global.
After putting <stdio.h> and all the other headers needed, I have 2 typedef struct and after that, I have put 11 static int variables and 3 static struct variables.
I have checked every single function if the struct variables have been storing the data properly, and apparently, only the void function that is first called in int main() stores the correct data into the struct variable.
When the 2nd void function is called, the global variables from the 1st void function contains no data at all.
Can anyone tell me if using the global variables for multiple functions to work is wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
typedef struct hero_data{
//... data
}hero;
typedef struct item_data{
//.... data
}item;
int totalwarrior = 0;
int totalitem = 0;
int toughtotal = 0;
int nimbletotal = 0;
int smarttotal = 0;
int skeptictotal[3] = {0};
int mystictotal[3] = {0};
int cursedtotal[3] = {0};
int brutetotal[3] = {0};
int shreddertotal[3] = {0};
int vanillatotal[3] = {0};
int typetotal = 0;
int typenum = 0;
int typechoice = 0;
int classchoice = 0;
static item curr3[10000];
static hero curr[10000];
static hero curr2[10000];
static hero smart[1][10000];
static hero nimble[1][10000];
static hero tough[1][10000];
static hero type[3][10000];
static hero skeptic[3][10000];
static hero mystic[3][10000];
static hero cursed[3][10000];
static hero brute[3][10000];
static hero shredder[3][10000];
static hero vanilla[3][10000];
static hero player1;
static hero player2;
int randbetween(int max, int min)
{
//... functioning
}
void mygets(char *name, int len, FILE * stream)
{
//... functioning
}
void available_hero(hero Class[3][10000],int typenum, int classtotal[],int classcode) //Shows the available hero based on Player's choice
{
//... functioning
}
void detail_hero(hero curr[3][10000],int classtotal[],int typenum)
{
//....functioning
}
void detail_item(item curr[10000],int whatitem)
{
//functioning
}
void pointer_conversion(hero *a, hero curr[10000], int total)
{
//....functioning
}
void TDpointer_conversion(hero *a, hero curr[3][10000], int total,int typenum)
{
//....functioning
}
void pointer_conversion2(item *a, item curr3[], int total)
{
//...functioning
}
void OD_conversion(int a[], int curr[],int typenum)
{
//....functioning
}
void TD_conversion(hero a[3][10000],hero curr[3][10000],int typetotal, int typenum, int typetotal2)
{
//....functioning
}
void TD_conversion2(hero a[3][10000],hero curr[3][10000],int typetotal[], int typenum, int typetotal2[])
{
//....functioning
}
void TD_conversion_class(hero a[1][10000],hero curr[3][10000],int classtotal[3], int typenum, int typetotal)
{
//....functioning
}
void binarycheck(int encoding, hero *dummy, int totalwarrior)
{
//....functioning
}
void check_compare_item(hero player)
{
//....functioning
}
void create_player(hero player)
{
//....functioning
}
void load_hero(hero curr[])
{
//....functioning
}
int main()
{
load_hero(curr);
load_item(curr3);
create_player(player1);
printf(""\n --> %s <---\n",player1.name); //struct hero contains the variable "name"
// Nothing gets printed while when I try to print the name within Create_player function, it works.
check_compare_item(player1);
}

When you pass a parameter by-value and changes you make to it inside the called function will not be visible in the caller (the callee is operating on a copy of the data).
Solution: send your data via pointers.
Even better: avoid static variables altogether. What benefit do they offer in this case that a regular variable does not?

If you use a global variable, why do you need to pass them to the function? You can directly use them from within your function without passing them through args. Passing the args is the problem here.
And are you using the static keyword to keep them private to the file? otherwise, avoid the static.

Related

Include variables in seperate file in C?

I created a structure item:
typedef struct item
{
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item;
I need 36 of them so I create an array item treasure[6][6];
For each item I insert the data as so:
strcpy(treasure[0][0].name, "name");
strcpy(treasure[0][0].desc, "none");
treasure[0][0].lp = 0;
treasure[0][0].shield = 0;
treasure[0][0].weapon = 200;
I do this 36 times and takes a lot of space in editor, my question: Can I put this in a separate .c/.h file maybe? I've been trying to but can't make it work.
Thanks for any help!
I suggest that use a file, like init.h with the following content
#include <string.h>
typedef struct item {
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item;
item treasure[1][1] = {
{{.name = "name", .desc = "none", .lp = 0, .shield = 0, .weapon = 200}}};
In that way you must be able to initialize the struct of you matrix 6, 6 in another file, then you must be able to access it from the main program calling it like this:
#include "init.h"
#include <stdio.h>
int main() {
printf("%s\n", treasure[0][0].name);
return 0;
}
I hope this work for you, there a another ways to initialize structs, but this one is what I use more often. You can find more information here
https://gcc.gnu.org/onlinedocs/gcc/Designated-Inits.html
If you want to learn how to do proper C program design from the start, then this is how.
The correct way to do this is to create an item.h and a item.c file. Together they form a "code module" (or class, if you will).
Your header file item.h should contain the typedef and header guards. You should write an initialization function too.
// item.h
#ifndef ITEM_H
#define ITEM_H
#include <string.h>
typedef struct {
char name[20];
char desc[100];
int lp;
int shield;
int weapon;
} item_t;
void item_init (item_t* item,
const char name[20],
const char desc[100],
int lp,
int shield,
int weapon);
#endif
You can then implement the init function in init.c:
// item.c
#include "item.h"
void item_init (item_t* item,
const char name[20],
const char desc[100],
int lp,
int shield,
int weapon)
{
strcpy(item->name, name);
strcpy(item->desc, desc);
item->lp = lp;
item->shield = shield;
item->weapon = weapon;
}
These two files, init.h and init.c are only concerned about the behavior of all item_t variables. You can expand them with more functions as you go. They do not and should not contain any actual data.
Now if you want to keep the data separate, you could create a separate pair of files for it like this:
// item_data.h
#include "item.h"
#define ITEMS_N 36
item_t* item_data_get (int item_n);
This is just a "getter" function that lets you access the data. The actual data is encapsulated in the .c file:
// item_data.c
#include "item_data.h"
static item_t items [ITEM_N] =
{
[0] = {.name="name", .desc="none", .lp=0, .shield=0, .weapon=200},
[1] = ... // fill up data here
};
item_t* item_data_get (int item_n)
{
return items[n];
}
If you later on want to change the data of a given item, you can do so by calling item_init(item_data_get(n), ...);

How to change pass a struct to a function by reference in c

#include <stdio.h>
struct player{
int life;
};struct player info;
void name(struct player *info);
int main(void)
{
info.life = 20;
name(&info);
printf(">>>>%d", info.life);
return 0;
}
void name(struct player *info)
{
info.life = 20
}
Hi, well this is just a practice code I am trying to pass a struct to a function by reference, but how do I change the value of the int in the struct? when i try to compile
info.life = 20; I get an error, what am i doing wrong? I also tried doing
*info.life = 20; but I also got an error. Thanks you guys! :)
Here:
void name(struct player *info)
{
info.life = 20;
}
that should be info->life. because info is a pointer.
I usually typedef my structs to make it more readable.
typedef struct _Player
{
int life;
} Player;
Then to access your struct or pass it in you would do:
void name(Player *pInfo)
{
pInfo->life = 20;
}
I also prepend a p for any pointer variable, so that you can easily see when you have a pointer or not.

C Private Variables Get and Set methods

I am working in C, and have some variables that I don't want to be global, but I do want to have get and set methods for them that can be accessed "Globaly" outside of the file. I am used to doing this in Java, but C is very different in this manner. Basically I am looking for something that follows this pseudo Code, but I have not been able to find anywhere with examples that I might look at.
main.c
#include data.h
set(b);
datalog.c
#include data.h
get(b);
data.c
private int c;
set(b){
c = b;
}
get(c){
return c;
}
You make the variable static. When a global variable is made static, its scope is restricted to the current file.
An example is as follows:
Filename: main.c
#include <stdio.h>
#include "header.h"
extern int get();
extern void set(int);
int main()
{
set(10);
printf("value = %d \n", get());
set(20);
printf("value = %d \n", get());
set(30);
printf("value = %d \n", get());
set(40);
printf("value = %d \n", get());
return 0;
}
Filename: header.h
#include <stdio.h>
int get(void);
void set(int);
Filename: header.c
#include "header.h"
static int value = 0;
int get(void)
{
return value;
}
void set(int new_value)
{
value = new_value;
}
Output:
$ gcc -Wall -o main main.c header.h header.c
$ ./main
value = 10
value = 20
value = 30
value = 40
$
If you want private variables in c, there are a number of techniques that can approximate a private variable, but the C language actually doesn't have a "protection" concept that extends to private, public, protected (as C++ does).
C will show the name of any variable (it's a requirement in C) so you must approach it with the idea of information hiding the type of the variable (making dereferencing quite difficult).
One trick is to define the variable as an void* with the actual variable type being known in only one .c module.
/* somefile.h */
extern void* counter;
/* somefile.c */
#include "somefile.h"
int actualCounter = 0;
void* counter = &actualCounter;
/* otherfile.c */
#include "somefile.h"
// we can see "counter", but we cannot "use" it here; because we don't have access
// to the real "hidden" type of "int".
A better method is to extend this idea using the struct keyword, and make pseudo-methods, like so
/* person.h */
struct s_person;
typedef Person struct s_person;
Person* new_Person(char* name);
void delete_Person(Person* person);
void Person_setName(Person* person, char* name);
char* Person_getName(Person* person);
/* person.c */
struct s_person {
char* name;
};
Person* new_Person(char* name) {
Person* object = (Person*)malloc(sizeof(struct s_person));
// duplicate the string for more security, otherwise constructor
// could manipulate the "private" string after construction.
object->name = strdup(name);
return object;
}
void delete_Person(Person* person) {
// some implementations pass a Person** to set the reference to 0
// this implementation requires that the caller sets his own references to 0
free(person->name);
free(person);
}
void Person_setName(Person* person, char* name) {
// free the old
free(person->name);
// duplicate the new to provide "out of simulated class" modification by malicious
// name setter.
person->name = strdup(name);
}
char* Person_getName(Person* person) {
// must return a copy, otherwise one can manipulate name
// from reference provided by Person_getName(...);
return strdup(person->name);
}
/* otherfile.c */
#include "Person.h"
/* Now we can hold Person "simulated objects", but we cannot */
/* manipulate their "state" without using the C simulated object */
/* methods */
int main(int argc, char** argv) {
Person* bob = new_Person("bob");
printf("%s\n", Person_getName(bob));
delete_Person(bob);
// critical or we hold a pointer to freed memory.
bob = 0;
return 0;
}
Techniques like this have several variants, one is to have a "public struct" with a void* pointer to the "private struct". One is to include the "methods" as function pointers in the "public struct" (a step towards supporting polymorphism), one is to actually write a full and proper C++ type system which attempts to resolve things exactly as C++ would (class hierarchies, polymorphisim, late binding, information hiding, etc).
Basically, you can get some "object-oriented-ness" without too much work, but as you add more features of -ornamentation, you will add more glue code (until it is much simpler to actually use an object-oriented programming language).
You can type:
static int c;
This way, the ".o" won't export the "c" variable.
By your example, you can try using some struct with this information. A struct is like a class with only public member variables (i.e. no functions). So consider something as follows
#include <stdio.h>
typedef struct _somestruct
{
int c;
} theStruct;
int getC(theStruct* obj)
{
if(obj == NULL)
return -1;
return obj->c;
}
void setC(theStruct* obj, int val)
{
if(obj == NULL)
return;
obj->c = val;
}
int main()
{
theStruct myStruct;
setC(&myStruct, 5);
printf("%d\n", getC(&myStruct));
return 0;
}
As you can see, C works only with objects and functions. But to get a global variable across all files, try static int c = 0;
The example above is nearly as close as you can possibly get to a "java-style" convention.
static int c;
int get(void) {
return c;
}
int set(int n) {
c = n;
}
You can improve on #RageD's answer by using function pointers:
#ifndef MYCLASS_H
#define MYCLASS_H
/********************************* MyClass.h **********************************/
// Typedef function pointers for usage clarity
typedef int (*GetInt)();
typedef void (*SetInt)();
typedef struct MyClass {
int Value;
GetInt GetValue;
SetInt SetValue;
} MyClass_t;
// Make the default class accessible to other modules
extern MyClass_t new_MyClass;
#endif
/********************************* MyClass.c **********************************/
#include <stdio.h>
static int getValue(MyClass_t* obj){
if(obj == NULL)
return -1;
return obj->Value;
}
static void setValue(MyClass_t* obj, int value){
if(obj == NULL)
return;
obj->Value = value;
}
// Default "constructor" of MyClass
MyClass_t new_MyClass = {0, &getValue, &setValue};
/*********************************** main.c ***********************************/
//#include "MyClass.h"
int main(){
// Create a default instance of the class
MyClass_t myClass = new_MyClass;
// Call the private (static) Getter function --> Prints 0
printf("%d\n", myClass.GetValue(&myClass));
// Set the instance's value by the Setter function
myClass.SetValue(&myClass, 9);
// Prints 9
printf("%d\n", myClass.GetValue(&myClass));
return 0;
}

C - memory management

I just wrote some C code:
#include <stdlib.h>
#include <time.h>
#include <string.h>
typedef struct {
void **data;
time_t lastModified;
} container;
container *container_init() {
container *c = malloc(sizeof(container));
void *data = NULL;
c->data = &data;
c->lastModified = time(NULL);
return c;
}
void *container_getData(container *c) {
void **containerData = c->data;
return *containerData;
}
// only pass manually allocated data that can be free()'d!
void container_setData(container *c, void *data) {
free(container_getData(c));
c->data = &data;
}
void container_free(container *c) {
free(container_getData(c)); // <--- THIS LINE
free(c);
}
int main(int argc, const char *argv[]) {
for (int i = 0; i < 100000000; i++) {
char *data = strdup("Hi, I don't understand pointers!");
container *c = container_init();
container_setData(c, data);
container_free(c);
}
}
My logic was the following: When I call container_setData(), the old data is free()'d and a pointer to the new data is stored. That new data will have to be released at some point. That happens for the last time during the call to container_free().
I have marked a line in the container_free() function. I would have sworn I'd need that line in order to prevent a memory leak. However, I can't use the line ("object beeing freed was not allocated") and there's no memory leak if I delete it. How does the string from my loop ever get released?!
Could someone explain where the error is?
c->data = &data;
stores the address of the pointer data (the argument to your function), not the actual pointer. I.e., you're storing a pointer to a temporary.
You could have built the container structure with just a void *data member.
To explain larsmans answer with code make these changes:
typedef struct {
void *data;
time_t lastModified;
} container;
void *container_getData(container *c) {
return c->data;
}
void container_setData(container *c, void *data) {
free(c->data);
c->data = data;
}
void container_free(container *c) {
free(c->data);
free(c);
}
And other changes too -- this just gets you on the right track.

Accessing members of the struct via void *

The solution consists of two parts, one is a static library that receives instances of struct from the user of the library. Library doesn't know what will be the type of structs, all it knows there will be two function pointers to it with a specific name.
Library Code
pre-compiled library has no way of knowing types of user structs, hence receiving via void*
void save(void *data) {
// library will save/cache user's object
data->registered(); // if register successful
}
void remove(void *data) {
// library will remove the object from memory
data->remove(); // if removed successful
}
User of the Library Code
struct Temp { // random order of fields
void (*custom1)();
void (*registered)();
void (*custom2)();
void (*remove)();
void (*custom3)();
}
void reg() {
printf("registered");
}
void rem() {
printf("removed");
}
void custom1() {}
void custom2() {}
void custom3() {}
var temp = malloc(struct Temp, sizeof(struct Temp));
temp->registered = reg;
temp->remove = rem;
temp->custom1 = custom1; // some custom functions
temp->custom2 = custom2;
temp->custom3 = custom3;
// calling library code
save(temp);
remove(temp);
Q. Is there a way for the Library to know how to iterate and go through member fields and see if there's a pointer to such function and call it available.
Is there a way for the Library to know how to iterate and go through member fields and see if there's a pointer to such function and call it available.
No there is not.
Your best bet is to create a structure in the library that has these members, and pass that structure instead of void*.
As #immibis said, there is no way for this to work (i.e. no way for the compiler to justify compiling such code) if the compiler does not know what the types of the data being passed to the function are.
Since you wanted to pass the objects along to the library without storing information about the type of each object in the library, you can fake polymorphism in C, by doing the following:
callback.h
#ifndef _CALLBACK_H_
#define _CALLBACK_H_
typedef struct {
void (*registered)();
void (*removed)();
} ICallback;
#endif _CALLBACK_H_
pre_comp.h
#ifndef _PRE_COMP_H_
#define _PRE_COMP_H_
#include "callback.h"
void save(ICallback* data);
void remove(ICallback* data);
#endif /* _PRE_COMP_H_ */
precomp.c
#include <stdlib.h> /* NULL */
#include "callback.h"
#include "pre_comp.h"
void save(ICallback *data) {
if (NULL != data && NULL != data->registered) {
data->registered(); // if register successful
}
}
void remove(ICallback *data) {
if (NULL != data && NULL != data->removed) {
data->removed(); // if removed successful
}
}
main.c
#include <stdio.h>
#include "pre_comp.h"
#include "callback.h"
struct Temp {
ICallback base; // has to be defined first for this to work
void (*custom1)();
void (*custom2)();
void (*custom3)();
};
// calling library code
void reg() {
puts("registered");
}
void rem() {
puts("removed");
}
int main() {
struct Temp data = {{reg, rem}};
save((ICallback*)&data);
remove((ICallback*)&data);
}
compiling
gcc pre_comp.c main.c
output
registered
removed
If the library has 0 information about the possible struct types, then you
cannot do it. The library has to get somehow the information or the offsets.
The only way I can think of is:
All register member have the same prototype
Pass the offset to the function.
I created an example of this
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
// function that does not know anything about any struct
void reg(void *data, size_t offset)
{
uintptr_t *p = (uintptr_t*) (((char*) data) + offset);
void (*reg)() = (void(*)()) *p;
reg();
}
struct A {
int c;
void (*reg)();
};
struct B {
int b;
int c;
void (*reg)();
};
void reg_a()
{
printf("reg of A\n");
}
void reg_b()
{
printf("reg of B\n");
}
int main(void)
{
struct A a;
struct B b;
a.reg = reg_a;
b.reg = reg_b;
reg(&a, offsetof(struct A, reg));
reg(&b, offsetof(struct B, reg));
return 0;
}
This prints:
$ ./c
reg of A
reg of B
I run it with valgrind and I did not get any errors nor warnings. I'm not sure if
this violates somehow strict aliasing rules or yields undefined behaviour
because of the uintptr_t* conversions, but at least it seems to work.
I think however, the more cleaner solution is to rewrite the register (btw. register
is a keyword in C, you cannot use that for a function name) function to
accept a function pointer and possible parameters, something like this:
#include <stdio.h>
#include <stdarg.h>
void reg(void (*func)(va_list), int dummy, ...)
{
if(func == NULL)
return;
va_list ap;
va_start(ap, dummy);
func(ap);
va_end(ap);
}
void reg1(int a, int b)
{
printf("reg1, a=%d, b=%d\n", a, b);
}
void vreg1(va_list ap)
{
int a = va_arg(ap, int);
int b = va_arg(ap, int);
reg1(a, b);
}
void reg2(const char *text)
{
printf("reg2, %s\n", text);
}
void vreg2(va_list ap)
{
const char *text = va_arg(ap, const char*);
reg2(text);
}
int main(void)
{
reg(vreg1, 0, 3, 4);
reg(vreg2, 0, "Hello world");
return 0;
}
This has the output:
reg1, a=3, b=4
reg2, Hello world
Note that reg has a dummy parameter. I do that because the man page of
stdarg says:
man stdarg
va_start():
[...]
Because the address of this argument may be used in the va_start() macro,
it should not be declared as a register variable, or as a
function or an array type.
You can take an approach similar to qsort and pass function pointers in addition to a void pointer to the structure.
Here is the function prototype for qsort, which is a function that can be used to sort arrays of any type:
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
It takes a function pointer that performs the comparison because without it qsort wouldn't know how to compare two objects.
This can be applied to your task with a function prototype like this:
int DoFoo(void *thing, void (*register)(void *), void (*remove)(void *))
This function takes a void pointer to your struct and then two functions that it can call when it needs to register or remove that struct. Having the functions be members of the struct is not required and I generally do not recommend it. I recommend reading up on qsort because it is does something similar to what you are trying to do.

Resources