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;
}
Related
How can I pass the variable address of the structure short name (color) to a function (fun) arguments.
#include <stdio.h>
void fun();
struct figure {
char name[30];
float field;
} color;
int main(void) {
fun();
return 0;
}
How to pass the variable address of the structure short name
To pass the address you only need &color.
Then the function needs to accept a pointer to struct figure.
It may look like:
#include <stdio.h>
#include <string.h>
struct figure{
char name[30];
float field;
} color;
void fun(struct figure *); // Function takes pointer to struct figure
int main(void){
strcpy(color.name, "Joe"); // Initialize color
color.field = 42.0;
fun(&color); // Pass address of color
return 0;
}
void fun(struct figure *c)
{
printf("%s\n", c->name); // Access color using the passed pointer
printf("%f\n", c->field);
}
Output:
Joe
42.000000
struct figure { ... }; would just introduce a new type named struct figure, whereas struct figure { ... } color; does two things (1) introduce above mentioned type and (2) define a variable named color of that type.
To pass an object of type struct figure to a function, write...
struct figure{
char name[30];
float field;
} color;
void fun(struct figure f) {
printf("%s %f\n", f.name, f.field);
}
int main(void){
struct figure myObj;
strcpy(myObj.name, "Hello!");
myObj.field = 1.0;
fun(myObj);
return 0;
}
You could also pass the address of such an object, which would then allow the function to alter the originally passed object as well:
void fun(struct figure *f) {
f->field = 2.0
printf("%s %f\n", f->name, f->field);
}
int main() {
...
fun(&myObj);
I'm writing a program that can modify rows and cols from a function of a function. I don't understand how to do pointer of a pointer.
void changeNum(int*setRows, int *setCol)
{
changeNum2(*setRows,*setCol);
}
void changeNum2(int*setRows, int *setCol)
{
*setRows=5;
*setCol=5;
}
int main() {
int*row=10;
int* col=10;
changeNum(&row,&col);
printf("%d %d",row,col);
return 0;
}
First
int*row=10;
int* col=10;
This is wrong. Assigning hardcoded address. You don't want this
int row=10;
int col=10;
How to get the address of the row and col?
&row and &col.
How to pass it to function?
Call it, changeNum(&row,&col);
void changeNum(int*setRows, int *setCol)
{
...
}
How to pass pointer to pointer?
void changeNum(int*setRows, int *setCol)
{
chnageNum2(&setRows, &setCol);
}
ChangeNum2 how it would change value?
void chnageNum2(int **setRows, int **setCol){
**setRows = 110;
**setCol = 110;
}
Can we do the same change using changeNum() only?
Yes we can do that.
void changeNum(int*setRows, int *setCol)
{
*setRows = 110;
*setCol = 110;
}
Definitely check this. Grab a book. It will help a lot.
The complete code will be
void changeNum(int*setRows, int *setCol)
{
changeNum2(&setRows,&setCol);
}
void changeNum2(int**setRows, int **setCol)
{
**setRows=5;
**setCol=5;
}
int main(void) {
int row=10;
int col=10;
changeNum(&row,&col);
printf("%d %d",row,col);
return 0;
}
#include <stdio.h>
void changeNum(int*, int*);
void changeNum2(int*, int*);
void changeNum(int* setRows, int *setCol) {
changeNum2(setRows,setCol);
}
void changeNum2(int* setRows, int *setCol) {
*setRows=5;
*setCol=5;
}
int main() {
int row=10;
int col=10;
changeNum(&row, &col);
printf("%d %d\n", row, col);
return 0;
}
It takes sometime to grasp that every C function parameter is passed by value. So you can safely pass setRows pointer to the second function simply by its value.
Also, it's necessary to declare previously the function changeNum2, I've included the declaration without parameter names to clarify it's possible.
I strongly recommend reading this book: https://en.wikipedia.org/wiki/The_C_Programming_Language, specially chapter 5 (Pointers and arrays).
You can find a PDF copy easily. It's where I finally learned this concept.
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) {...}
...
}
void dispatch_for(dispatch_queue_t *queue, long number, void (* work)(long)){
int loop = number;
int i;
task_t *ctask;
for(i = 0; i<loop;i++){
ctask = create_task((void *)work,number,"for_test");
dispatch_async(queue,ctask);
}
}
task_t *task_create(void (* work)(void *), void *param, char* name){
//do something
}
I'm getting work as a function and need to pass it to the function create_task..(1st parameter)
How should i pass it?
name of the function without the parentheses is the pointer to that function :
void work(void) {
...;
}
void main(void) {
task_create(work, void, void);
}
Just use the identifier like any other parameter:
dispatch_for(queue, number, work);
The easiest thing would be a typedef to the wanted function type. So you can do
typedef void workfunc_t(void *);
workfunc_t sample_workfunc; // in order to ensure type-correctness
void workfunc_t(void *)
{
// ...
}
void dispatch_for(dispatch_queue_t *queue, long number, workfunc_t * work)
{
int loop = number;
int i;
task_t *ctask;
for(i = 0; i<loop;i++) {
ctask = create_task(work, number, "for_test");
dispatch_async(queue,ctask);
}
}
task_t *task_create(workfunc_t work, void *param, char* name){
//do something
}
The function work doesn't have the same signature in dispatch_for and task_create (the argument is a pointer in one, a long in the other)
It seems strange you want to use the same function in both cases
Since you're using C, and work is a type void (*)(long), but you want to make it a void (*)(void*), simply re-cast the type of work (this is can be done the easiest by using a typedef)
//declare somewhere at a global level
typedef void (*task_create_func)(void*);
//at the point where you want to call task_create
task_create((task_create_func)work, PARAM1, PARM2);
Alternatively, if you don't want to deal with typedefs, you can simply do the cast using the desired pointer-type at the point-of-call like so:
task_create((void (*)(void*))work, PARAM1, PARAM2);
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.