i am new to C lang. My code is like:
int afunc(const struct datas *mydata, void *value) {
value = &mydata->astring; // astring is in structure char[20]
return 0;
}
int main (...) {
...
const char *thevalue;
if (!afunc(thedata, &thevalue) {...}
...
}
The address in var value is only in the function, when the function is over variable thevalue is still empty... So, I want pointer on array in the structure.
How should I fix that?
fix like this
#include <stdio.h>
struct datas {
char astring[20];
};
int afunc(const struct datas *mydata, void *value) {
*(const char **)value = mydata->astring;
return 0;
}
int main (void) {
struct datas mydata = { "test_data" }, *thedata = &mydata;
const char *thevalue;
if (!afunc(thedata, &thevalue)) {
puts(thevalue);
}
}
You use pointers to pass variables which must be modified in C. However, if you want to modify a pointer value, you must pass a pointer to that pointer, and then dereference the pointer in the function. Like this:
int afunc(const struct datas *mydata, void **value) {
*value = &mydata->astring; // astring is in structure char[20]
return 0;
}
int main (...) {
...
const char *thevalue;
if (!afunc(thedata, &thevalue) {...}
...
}
Related
I'm having a problem in line: novo->conta.nome_cliente = valor2;. In this dynamic stack structure. Empilhar is a function to push a new element to the stack. Why i cant assign a new value to the structure inside the stack?
struct conta_de_luz
{
int cod_cliente;
char nome_cliente[40];
};
typedef struct Item {
struct conta_de_luz conta;
struct Item *anterior;
} Elemento;
void Inicializar(Elemento **topo) {
*topo = NULL;
}
int EstaVazia(Elemento **topo) {
if(*topo == NULL)
return VERD;
else
return FALSO;
}
void Empilhar(Elemento **topo, int valor, char valor2) {
Elemento *novo;
novo = (Elemento *) malloc(sizeof(Elemento));
novo->conta.cod_cliente = valor;
novo->conta.nome_cliente = valor2;
novo->anterior = *topo;
*topo = novo;
}
The problem is that line novo->conta.nome_cliente = valor2; assigns a char to something that is a string defined as char nome_cliente[40];.
So your function probably should have been void Empilhar(Elemento **topo, int valor, char* valor2). But that would still assume the value of valor2 remains in memory for the lifetime of topo.
Better would be void Empilhar(Elemento **topo, int valor, const char* valor2) and then use strcpy(novo->conta.nome_cliente, valor2);.
But this assumes valor2 including its NULL-terminator always fits within 40 characters. If this assumption is not guaranteed it's better to duplicate the string using strdup(). You will then also need to free() this seperately this in your cleanup function.
I've encountered a problem where my array of structs didn't get assigned with value when I assign them value in a function.
Here are the struct declarations:
typedef struct{
int length;
int width;
char texture;
int xpos;
int ypos;
}prop_info;
typedef struct{
int init_xpos;
int init_ypos;
int index;
prop_info prop[100];
}room_info;
And here are the functions:
void info_setup(room_info room,int init_xpos,int init_ypos,int index)
{
room.init_xpos=init_xpos;
room.init_ypos=init_ypos;
room.index=index;
}
void prop_setup(room_info room,int prop_index,int length,int width,char texture,int xpos,int ypos)
{
room.prop[prop_index].length=length;
room.prop[prop_index].width=width;
room.prop[prop_index].texture=texture;
room.prop[prop_index].xpos=xpos;
room.prop[prop_index].ypos=ypos;
}
room_info room_lobby;
void init_rooms()
{
info_setup(room_lobby,0,0,0);
prop_setup(room_lobby,0,1,1,'X',5,5);
}
And when I use the "init_rooms()" function in the main function:
int main()
{
init_rooms();
printf("%d",room_lobby.prop[0].xpos);
}
The printf only outputs a 0, and if I try to print out the "room_lobby.prop[0].texture", which is a char, it will only print a space when it should print a X.
Thanks in advance!
When a structure is passed to a function, the function receives a copy of the structure, not a reference to the structure. So any changes the function makes only affect the copy, and not the original structure.
To make changes to the original structure, the caller needs to pass the address of the structure, and the function parameter needs to be a pointer to the structure.
So the code should look like this:
void info_setup(room_info *room,int init_xpos,int init_ypos,int index)
{ // ^--- declare room as a pointer
room->init_xpos=init_xpos;
room->init_ypos=init_ypos;
room->index=index;
// ^^--- access the structure members using pointer notation
}
void prop_setup(room_info *room,int prop_index,int length,int width,char texture,int xpos,int ypos)
{
room->prop[prop_index].length=length;
room->prop[prop_index].width=width;
room->prop[prop_index].texture=texture;
room->prop[prop_index].xpos=xpos;
room->prop[prop_index].ypos=ypos;
}
room_info room_lobby;
void init_rooms(void)
{
info_setup(&room_lobby,0,0,0);
prop_setup(&room_lobby,0,1,1,'X',5,5);
// ^--- pass the address of the structure
}
int main(void)
{
init_rooms();
printf("%d\n",room_lobby.prop[0].xpos);
}
'struct parameter' is a value parameter. So the value will be copied into function, other then the variable. If you want change the value of a variable,
you should use reference or address of struct parameter, like this:
void info_setup(room_info& room,int init_xpos,int init_ypos,int index)
{
room.init_xpos=init_xpos;
room.init_ypos=init_ypos;
room.index=index;
}
void prop_setup(room_info& room,int prop_index,int length,int width,char texture,int xpos,int ypos)
{
room.prop[prop_index].length=length;
room.prop[prop_index].width=width;
room.prop[prop_index].texture=texture;
room.prop[prop_index].xpos=xpos;
room.prop[prop_index].ypos=ypos;
}
or
void info_setup(room_info* room,int init_xpos,int init_ypos,int index)
{
room->init_xpos=init_xpos;
room->init_ypos=init_ypos;
room->index=index;
}
void prop_setup(room_info* room,int prop_index,int length,int width,char texture,int xpos,int ypos)
{
room->prop[prop_index].length=length;
room->prop[prop_index].width=width;
room->prop[prop_index].texture=texture;
room->prop[prop_index].xpos=xpos;
room->prop[prop_index].ypos=ypos;
}
I want to pass multiple arguments to a function using a void pointer.
void* function(void *params)
{
//casting pointers
//doing something
}
int main()
{
int a = 0
int b = 10;
char x = 'S';
void function(???);
return 0;
}
I know that I have to cast them to a certain variable in my function but I do not know how I can pass my 3 arguments as one void pointer to my function.
I have searched for this problem know quite some time but I could not find anything that would help me.
You could do it like this:
struct my_struct
{
int a;
int b;
char x;
}
void * function(void * pv)
{
struct my_strcut * ps = pv; /* Implicitly converting the void-pointer
/* passed in to a pointer to a struct. */
/* Use ps->a, ps->b and ps->x here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct s = {42, -1, 'A'};
void * pv = function(&s);
}
Following up on the OP's update:
struct my_struct_foo
{
void * pv1;
void * pv2;
}
struct my_struct_bar
{
int a;
int b;
}
void * function(void * pv)
{
struct my_strcut_foo * ps_foo = pv;
struct my_struct_bar * ps_bar = ps_foo->pv1;
/* Use ps_foo->..., ps_bar->... here. */
return ...; /* NULL or any pointer value valid outside this function */
}
Use it like this
int main(void)
{
struct my_struct_bar s_bar = {42, -1};
struct my_struct_foo s_foo = {&s_bar, NULL};
void * pv = function(&s_foo);
}
The void* is used as a pointer to a "generic" type. Hence, you need to create a wrapping type, cast convert to void* to invoke the function, and cast convert back to your type in the function's body.
#include <stdio.h>
struct args { int a, b; char X; };
void function(void *params)
{
struct args *arg = params;
printf("%d\n", arg->b);
}
int main()
{
struct args prm;
prm.a = 0;
prm.b = 10;
prm.X = 'S';
function(&prm);
return 0;
}
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.
How would I create an array of ten function pointers? What I have is a for loop, and I want to set a function pointer to a different function on each iteration. so:
//pseudocode
for i (0..10)
function = array_of_functions[i];
//...
// Define alias for function pointer type for convenience
typedef void (*action)(int);
// Example function
void print(int) { ... }
action fs[10] = { print, ... };
for (int i = 0; i < 10; ++i)
{
action f = fs[i];
// Call it somehow
f(i * i);
}
This code:
return_t (*array_of_functions[10])(arg1_t, arg2_t);
Declares "array_of_functions" as a 10-element array of function pointers where each pointed-to function takes two arguments of type arg1_t and arg2_t and returns type return_t. Replace types and adjust the number of arguments as appropriate.
Any time you have to deal with ugly function pointer syntax it's better to use a typedef.
#include <iostream>
void a(int i)
{
std::cout<<"a: "<<i<<std::endl;
}
void b(int i)
{
std::cout<<"b: "<<i<<std::endl;
}
typedef void (*fn)(int);
int main(int argc, char**argv)
{
fn foo[2];
foo[0] = a;
foo[1] = b;
for(size_t i = 0; i < sizeof(foo) / sizeof(foo[0]); ++i)
{
foo[i](i);
}
return 0;
}
The simplest way to do it is to create a typedef for your function, and then declare an array with that type. To create a typedef for the function: typedef returntype (*typedefname)(argtype1,argtype2,...,argtypeN); EX:
#include <stdio.h>
#include <stdlib.h>
typedef void (*functype)();
void func1()
{
//...
}
void func2()
{
//..
}
//...
void func10()
{
//...
}
int main(int argc, char* argv[])
{
functype array[] =
{
&func1,
&func2,
&func3,
&func4,
&func5,
&func6,
&func7,
&func8,
&func9,
&func10
};
// Use the array...
return 0;
}
T (*array_of_functions[10])();
Where T is the return type of each function (all functions return the same type, naturally). Things get tricky if you want to store pointers to functions with different numbers/types of parameters:
int foo(void) {...}
int bar(int x) {...}
int bletch(double y, double z) {...}
...
int (*array_of_functions[10])() = {foo, bar, bletch, ...};
If so, you'll have to keep track of what number and types of parameters each function requires somehow so you can call it correctly.
I'm actually kind of down on typedefs for function pointer types; they tend to obscure as much as they simplify.