Pointer to pointer , values not updating - c

global.h
typedef enum _global_list {
TEST_VAR1,
TEST_VAR2
} list;
/*Mapper between enum varibales and global variable*/
typedef struct _var_map{
list list_type;
void *ptr;
} var_map;
/*struct to hold global variable*/
typedef struct _glo_ptr{
int *ptr1;
float *ptr2;
} g_ptr;
g_ptr ptr;
void update_global(list ,void *);
global.c
#include "globals.h"
static var_map map[2] = { { TEST_VAR1, &(ptr.ptr1) }, { TEST_VAR2, &ptr.ptr2 } };
update_global(list var, void* ptr){
if (map[0].list_type == TEST_VAR1){
map[0].ptr = ptr;
}
}
testfile.c
#include "globals.h"
int main(){
int test_var1=0;
update_global(TEST_VAR1, &test_var1);
test_var1=4;
printf("%d",*ptr.ptr1); //should contain value 4
}
What I'm trying to do is: my g_ptr should contain latest values pointed by it. But in pointer to pointer I'm doing somewhere some mistake leading not proper update of values. For exmple: my final g_ptr.ptr1 value should contain 4. What needs to be corrected in this?

Problem is you're changing the actual pointer in your map, but not affecting the data being pointed to:
map[0].ptr = ptr;
Should be:
*(int**)map[0].ptr = (int*)ptr;
The motivation behind your program is a little suspect, but I believe this will give you what you are looking for... I will keep my distance =)
Oh, I noticed another thing... You declare separate instances of ptr. When you include global.h in each source file, they see ptr as a private static variable. That's not what you want. You need to declare and define it like this:
global.h
extern g_ptr ptr;
global.c
g_ptr ptr;

Related

Struct with pointer to function

can you please explain in details this line of code inside struct:
There is a pointer to function but why would you reference it to struct?
void (*function)(struct Structure *);
what does this mean
(struct Structure *)?
(struct Structure *)
It means that the function have a struct Structure * argument. Actually it will make more sense with (struct Structure *variable of struct).
In this way, you can use a pointer to point a struct and should put the address of the struct variable which can be used in the function.
#include <stdio.h>
typedef struct circle{
int rad;
int area;
} Circle;
void ShowCircleInfo(Circle *info)
{
printf("rad value: %d\n", info->rad);
printf("area value: %d", info->area);
}
int main(void)
{
Circle circle_one;
circle_one.rad = 2;
circle_one.area = 3;
ShowCircleInfo(&circle_one);
return 0;
}
void (*function)(struct Structure *); declares function to be a pointer to a function that has a parameter of type struct Structure * and does not return a value.
For example
#include <stdio.h>
struct Structure {
int a;
void (*function)(struct Structure *);
};
void foo(struct Structure *a) {
if (a->function == NULL) a->function = foo;
a->a++;
printf("%d\n", a->a);
}
int main(void) {
struct Structure a = {42, foo};
struct Structure b = {0}; // don't call b.function just yet!!
a.function(&b); // foo(&b)
b.function(&a); // foo(&a)
}
See code running at https://ideone.com/7E74gb
In C, function pointer declarations have almost the same structure as function headers.
Only the function name will change to have some parantheses and a "*" in it, and the arguments won't have names, because only their types are important when using pointers (we don't access the values of the arguments, so we don't need their names).
They basically look like this:
<return_value> (*<function_name>)(<argument_list>)
So, for example, the function pointer for the function
void swap(int* a, int* b);
would be
void (*swap_ptr)(int*, int*);
Notice that the name of the pointer is in the place of the name of the function, and looks a bit odd compared to normal pointer declarations.
An excellent reading on this topic (you can skip the C++ stuff): https://www.cprogramming.com/tutorial/function-pointers.html

C Declare array of struct/pointer to array of structs

I have an example tutorial with 2 files, "functions.c" and "functions.h" which contain the prototypes and the body of the functions.
In the example there isn't the main that containing the declaration of the array of struct/pointer to array of structs and the calls to the functions.
functions.c:
#include "functions.h"
const char *getTeamA(const sTest *p)
{
return p->teamA;
}
void setTeamA(sTest *p, char *s)
{
strcpy(p->teamA, s);
}
int getNum(const sTest *p)
{
return p->num;
}
void setNum(sTest *p, int i)
{
p->num = i;
}
functions.h:
#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHAR 20
#define SIZE 5
typedef struct {
char teamA[MAX_CHAR];
int num;
// ...
} sTest;
const char *getTeamA(const sTest *p);
void setTeamA(sTest *p, char *s);
int getNum(const sTest *p);
void setNum(sTest *p, int i);
#endif /* FUNCTIONS_H_ */
So my question is
How can i declare the struct according to the code written above?
So for example:
int main()
{
sTest data[SIZE]; //size isn't important
sTest *dataPtr = data;
setTeamA(dataPtr[0].teamA, "name1");
// ...
printf("%d", getNum(dataPtr[1].num)); // just an example. i know that it isn't initialized
// ...
return 0;
}
Is this the correct way? Or is there a better way to declare variables and pass them to the functions?
The important thing is that i have to stick to the code written in functions.c and functions.h, so the functions cannot directly modify the struct data, you need to use pointers (because there are member selection operator "->" in functions.c).
You don't need to have dataPtr. You can do the exact same thing by doing data[i], since you declared data as an array of sTests, and so data points to the first element in the array.
Let's deconstruct what you're doing when you're calling setTeamA(dataPtr[0].teamA, "name1"). You're trying to set the first sTest struct in the data array to have "name1" as the teamA field. Notice that the prototype for setTeamA() actually takes in a sTest *p. In your example, you're passing in the teamA field. So what you really want to call is setTeamA(&dataPtr[0], "name1"). This translates to the pointer pointing to the data at dataPtr[0].
While this works, as I said before, the dataPtr is unecessary. So this is equivalent to:
setTeamA(&data[0], "name1").
Also worth noting, you can simply write:
setTeamA(data, "name1")
since data is already a pointer to the first element in the array.
Use
setTeamA(&data[0], "name1")
It indexes to index 0 and then takes the reference (which is a pointer) of the result therefore making the type an sTest* then the setTeamA function will do it's job setting the teamA field.
That dataPtr variable is useless here.

how to control struct member behavior with struct const pointer as function parameter?

I have a C code, somewhat similar to this:
struct st
{
int *var;
}
void fun(st *const ptr)
{
// considering memory for struct is already initialized properly.
ptr->var = NULL; // NO_ERROR
ptr = NULL; // ERROR, since its a const pointer.
}
void main()
{
//considering memory for struct is initialized properly
fun(ptr);
}
I dont want to declare int *var as const in the structure definition, so as not to mess with the huge code base. Not looking to make any change in the structure definition
Is there any way in C, to get an error for the NO_ERROR line
ptr->var = NULL; // NO_ERROR ?
Just declare the parameter with const, so the ptr is a pointer to a const object:
void fun(const struct st* ptr)
Your declaration makes ptr to be constant, but not the object to which it points. Also don't miss struct keyword
void fun(struct st *const ptr);
Instead you should use
void fun(const struct st *ptr);
Such declaration allows to change pointer but not the object to which it points.
Keep this in mind:
With type* const ptr, you cannot change the pointer but you can change the pointed data
With const type* ptr, you can change the pointer but you cannot change the pointed data
So all you need is to replace struct st* const ptr with const struct st* ptr.
Superb! Thank you so much guys!
I did this -
void fun(const struct st *const ptr);
and I was able to get an error while changing both ptr and ptr->var .. Just what I needed..

Setting a struct pointer to equal the address of another struct

I'm trying to set ptr to point at the first element in an array of structs so that when I go back to my main function, I can mess with it (theres reasons why I can't use vArray[0] in the main).
With this code though, its only allowing me to access the structs members in the alg function. Once its return back to main, all of its elements are now null. (I'm thinking it has something to do with a pass-by-value/pass-by-reference problem). Any way to fix this?
void alg(struct vars v[], struct vars *ptr)
{
ptr = &vars[0];
printf("%s", ptr->value); //this works here
}
int main()
{
struct vars vArray[100]; //this has been filled earlier in the code
struct vars *ptr;
alg(vArray, ptr);
printf("%s", ptr->value); //but now this returns null here
}
You need "Need of Pointer to pointer" to reflect change in function alg() in main function.
Do it as:
void alg(struct vars v[], struct vars **ptr)
{
(*ptr) = &vars[0];
printf("%s", (*ptr)->value); //this works here
}
And call function main as: alg(vArray, &ptr);
Note: both ptr in main and ptr in function alg() are two different variable.
Btw for learning purpose it is good to write function otherwise you can simply do it in one line as: struct vars *ptr = vArray;. Note array name decays into address of first element in this expression.
You have to read about pointer to pointer.
Check this code:
#include <stdio.h>
#include <stdlib.h>
struct vars {
int data;
};
void alg(struct vars *v, struct vars **ptr);
int main()
{
struct vars *ptr;
struct vars vArray;
vArray.data = 10;
alg(&vArray, &ptr);
printf("main : %d\n", ptr->data);
}
void alg(struct vars *v, struct vars **ptr)
{
*ptr = v;
printf("fun : %d\n", (*ptr)->data);
}
output :
fun : 10
main : 10
In short use double pointer it will solve your problem

C Strings in Structs

I want my struct to carry a string. I defined it like so:
typedef struct myStruct {
char* stringy
} myStruct
and a function
free(char *stringy){
//structObj is a struct object
structObj->stringy = stringy
}
Is this correct? I have a feeling that since it's a local variable, stringy will be lost, and the pointer will point to garbage.
Sorry, new with C.
It would be garbage if you were somehow using char** stringy, but structObj->stringy = stringy means "you know the thing that stringy points to? Now structObj->stringy points to that". Of course, it is still possible to unset the value which the pointer is pointing to, and at that point dereferencing will yield garbage.
Here's an example to make it clearer:
#include<stdio.h>
typedef struct mStruct {
char* stringy;
} myStruct;
myStruct * structObj;
void doSomething(char* stringy)
{
structObj->stringy = stringy;
}
int main(int argc, char* argv)
{
char* a = "abc\n";
structObj = malloc(sizeof(myStruct));
doSomething(a);
a = "qxr\n";
printf(structObj->stringy);
}// prints "abc\n"
If stringy is defined in callers of free function, as long as they keep the actual string in its place (where stringy points), no problem.
There is not any local variable declaration in your code.
You have to declare:
typedef struct myStruct {
char* stringy
} myStruct;
free(char *stringy){
myStruct *structObj;
structObj->stringy = stringy;
}
Pay attention to the semicolon that I've added to the end of the typedef declaration.
This was not not in your code.
The object structObj is a struct whose type is myStruct.
Now, your parameter stringy comes from another site, it is not lost.
But the struct structObj will have duration only inside your "free" function.
EDIT
I have fixed an error: the right declaration has to be "pointer to structObj", which is done in this way:
myStruct *structObj;
Observe that now myStruct is a non-initialized pointer, so the following assignment is legal:
structObj->stringy = stringy;
but will not work.
However I think this goes beyond the scope of the original question...
myStruct is type which you defined for your struct myStruct .that to you need to create an object before using.
you need to do like this:
typedef struct myStruct {
char *stringy;
} myStruct_t; //user defined data type
myStruct_t *obj;
// you need to allocate memory dynamically.
obj= (myStruct_t *) malloc(sizeof(myStruct_t));
usage:
scanf("%s",obj->stringy);
printf("%s",obj->stringy);
in function:
my_free(char *str) //str is local string
{
obj->stringy=str;
}
your can also try this code :
typedef struct myStruct {
char stringy[20]; //char *stringy
} myStruct_t; //user defined data type
myStruct_t obj; //object creation
usage:
scanf("%s",obj.stringy);
printf("%s",obj.stringy);
in function:
my_free(char *str) //str is local string
{
strcpy(obj.stringy,str);
}
You're correct that as soon as what it points to goes out of scope, it will point to garbage: this is a dangling pointer. You'll need to allocate some memory and perform a copy to fix this:
add_string(my_struct* s, const char* c)
{
size_t len = strlen(c);
s->file = malloc(len + 1);
strcpy(s->file, c);
}
Don't forget that you'll need to free it when you're done:
void destroy_struct(my_struct* s)
{
free(s->file);
free(s);
}

Resources