Pointer to a struct array - c

How can I make a pointer to a member of a struct, thats an array of ints. This is how the struct looks like:
typedef struct {
volatile int x[COORD_MAX];
volatile int y[COORD_MAX];
volatile int z[COORD_MAX];
//... other variables
} coords;
coords abc;
abc is a global variable.
Now, I would like to get pointers to x,y and z arrays and save them to another array. Then acces them through passing a wanted index. Here is what I mean:
void test(int index1, int index2)
{
static volatile const int* coords_ptr[3] = {abc.x, abc.y, abc.z};
coords_ptr[index1][index2] = 100;
}
So index1 would select which type of coordinates to choose from (x,y,z). And index2 would select which index of the coordinates to change.
Please note, that this is just a simplification of the code I am working on. But the principle is the same.
Thanks in advance!
EDIT:
I've written wrong code. Sorry for the confusion, this should be right now.

There's only one small mistake: you made the pointers point to const volatile int, which prevents you from writing to them.
Just write
static volatile int* coords_ptr[3] = {abc.x, abc.y, abc.z};
and it'll work.

#include <stdio.h>
#define COORD_MAX 3
typedef struct {
volatile int x[COORD_MAX];
volatile int y[COORD_MAX];
volatile int z[COORD_MAX];
} coords;
coords abc;
void test(int index1, int index2)
{
static volatile int* coords_ptr[3] = {abc.x, abc.y, abc.z};
coords_ptr[index1][index2] = 100;
}
int main()
{
test(0, 0);
test(1, 1);
printf("%i %i\n", abc.x[0], abc.y[1]);
return 0;
}
output:
100 100

Related

Init a const var in a struct after the struct variable is created

I have a c struct that has a const variable.
typedef struct {
u32 status;
const u32 dir_search_idx;} FS_OBJ;
What I would like to do is init the const variable in a function once I have created the struct object. I guess I want to do something similar to what a constructor would do in c++. Is it possible to do something similar in c? Thanks
This should work perfectly fine if you are using C99 or newer and want to initialize the const variable when creating the struct:
FS_OBJ obj = { .status = /* something */, .dir_seach_idx = /* something */ };
You can't modify the const variable after creating the struct. Then you would have to remove the const keyword as mentioned by user3386109 in the comments.
I think const is not the right tool for what you are looking for. You can put data (structs) and behavior (functions) in a *.c file and provide public functions in the corresponding header file. This way you can mimic the equivalent c++ code that you want and hide the data and of course, you can define a constructor. A great book that might help is The GLib/GTK+ Development Platform. In chapter 3 you can find a good introduction to Semi-Object-Oriented Programming in C.
Here is a possible implementation, not necessarily the best one:
/src/main.c
#include <stdio.h>
#include "point.h"
int main()
{
Point *p1 = init(6, 7);
printf("%d\n", getX(p1));
printf("%d\n", getY(p1));
Point *p2 = init(12, 14);
printf("%d\n", getX(p2));
printf("%d\n", getY(p2));
setX(p2, 16);
printf("%d\n", getX(p2));
setY(p2, 16); /* error; we want y to initialize once and remain constant. Also accessing y with p2->y is an error too. */
printf("%d\n", getY(p2)); /* getY is ok */
freep(p1);
freep(p2);
}
/src/point.h
typedef struct _Point Point;
Point *init(int, int);
int getX(Point *);
void setX(Point *, int);
int getY(Point *);
void freep(Point *);
/src/point.c
#include <stdlib.h>
#include "point.h"
struct _Point{
int x;
int y;
};
Point *init(int x, int y)
{
Point *temp;
temp = malloc(sizeof(Point));
temp->x = x;
temp->y = y;
return temp;
}
int getX(Point *p)
{
return p->x;
}
void setX(Point *p, int x)
{
p->x = x;
}
int getY(Point *p)
{
return p->y;
}
void freep(Point *p)
{
free(p);
}
Furthermore, if we need a private method in our class, we do not provide a declaration of it in the header and also we use static to restrict its access within the class's file.

Discussion around functionpointers in array of structs. What are good practises?

is there a more compact way for using function pointers inside a struct ?
Do I really need to type defining the function pointer? I tried without but received type errors. Are there any hazards, or anything that I've done that is against good code practice?
#include <stdio.h>
#include <math.h>
void lineFunc(int* a)
{
int x1 = a[0];
int y1 = a[1];
int x2 = a[2];
int y2 = a[3];
double length = sqrtf( pow( (x1-x2),2 )+ pow((y1-y2),2) );
printf("%f\n", length);
}
void areaFunc(int* a)
{
int base = a[0];
int height = a[1];
int area = base*height;
printf("%d",area);
}
typedef void (*Operation)(int* a );
typedef struct CALC_TYPE
{
Operation opt
} CALC;
int main()
{
int lineArg[4] = {1 , 2, 3, 4}; //x1, y1, x2, y2
int areaArg[2] = {5,10}; // base, height
void (*lineCalc)(int*);
void (*areaCalc)(int*);
lineCalc = lineFunc;
areaCalc = areaFunc;
CALC line;
CALC area;
CALC* cmdArray = calloc(2,sizeof(CALC));
line.opt = lineFunc;
area.opt = areaFunc;
cmdArray[0]=line;
cmdArray[1]=area;
cmdArray[0].opt(lineArg);
cmdArray[1].opt(areaArg);
return 0;
}
is there a more compact way for using function pointers inside a struct ?
No.
Do I really need to type defining the function pointer?
No, but it makes your code much more readable because the notation for function pointers is arcane. You could have instead written.
typedef struct CALC_TYPE
{
void (*opt) (int*);
} CALC;
Are there any hazards, or anything that I've done that is against good code practice?
Not really. Making a struct that only contains 1 thing is questionable, but it's obviously a learning exercise.
The typedef Operation and some variables are useless. The struct too but If I've understood you, you want to keep it. So here is a more compacte way:
#include <stdio.h>
#include <math.h>
#include <stdlib.h> // calloc
void lineFunc(int* a)
{
// ...
}
void areaFunc(int* a)
{
// ...
}
typedef struct CALC_TYPE
{
void (*opt)(int *a);
} CALC;
int main()
{
int lineArg[4] = {1 , 2, 3, 4}; //x1, y1, x2, y2
int areaArg[2] = {5,10}; // base, height
CALC *cmdArray = calloc(2, sizeof(CALC));
cmdArray[0].opt = lineFunc;
cmdArray[1].opt = areaFunc;
cmdArray[0].opt(lineArg);
cmdArray[1].opt(areaArg);
free(cmdArray); // 1 malloc/calloc => 1 free
return 0;
}
EDIT:
Are there any hazards, or anything that I've done that is against good
code practice?
Include stdlib.h to use calloc
Don't forget to free dynamically allocated memory
Why pow then sqrtf then store in double ? Use sqrt instead
You could avoid the use of a struct here
One additional point that I did not see in the other answers concerns a benefit of struct usage: function prototype stability. Even if a struct starts out with a single variable, future requirements for the struct may force more variables to be added. Because of the way struct variables are passed as arguments, prototype's of functions written to use the original single single variable struct, will not be broken when additional variables are added.
For example, your struct can be defined as:
typedef struct CALC_TYPE
{
Operation opt
} CALC;
Or:
typedef struct CALC_TYPE
{
Operation opt
int a;
float b;
} CALC;
Without forcing change to a function that calls it.:
void func(CALC *c)
{
...
}
It's a great way to allow changes to the number of items that need to be passed as data without changing the argument list.
Using a modification of your area function, consider the following struct that was initially designed to support area measurements:
typedef struct
{
int length;
int width;
}DIM;
int areaFunc(DIM *d)
{
return d->length*d->width*d
}
Later a requirement for the struct to support volume forces the addition of a variable:
typedef struct
{
int length;
int width;
int height;
}DIM;
Adding the new variable to the struct does not break the existing areaFunc(), but also supports the new function:
int volumeFunc(DIM *d)
{
return d->length*d->width*d->height;
}

Accessing a struct without the struct being global

I've got a struct called members which contains a bunch of char arrays and integers. The struct has been declared in Header.h and defined it by "struct members pt" in source.c, inside main. From here a for-loop is being runned 5 times and adding variables to the character arrays and ints in pt[x].
Now I need to be able to access this from a function called void search(int a); (Should probably not be a void since I want it to return a value. But I'll fix that later)
What void search is supposed to do is basicly
int willReturn[10];
int b = 0;
for(int x = 0; x<a; x++)
{
if(pt[x].hasPayed == 0)
{
willReturn[b] = x;
b++;
}
}
There might be something wrong about that code, but the thing that I need to know is how I can access pt[x].hasPayed.
Any ideas?
I do not want to use any global variables.
Thank you in advance.
Below sample code might help you.
header.h
struct members {
int hasPayed;
};
main.c
#include <stdio.h>
#include <string.h>
#include "main.h"
typedef struct members MEMBERS;
void print_member(MEMBERS *pt) {
int i;
for(i =0 ; i< 10; i++)
{
printf(" %d\n",pt[i].hasPayed);
}
}
void main () {
MEMBERS pt[10];
int i;
for(i =0 ; i< 10; i++)
{
pt[i].hasPayed= i;
}
print_member(pt);
}
Instead of print_member code your search logic.
Pass a pointer to pt as a paraamter to search. e.g void search(int a, struct members *pt).
Another way if you don't want to pass pointers. Place pt in a function as a static variable.
struct members** ____get_pt(){
static struct members pt[ /* size */ ];
/*
or for dynamical size,
static struct members* pt;
*/
return &pt;
}
// Define a macro for convenience, above where you want to use 'pt'.
#define PT (*____get_pt())
Then you can use PT[x].hasPayed everywhere, without global variables.
However, this could do not improve your code ...

Initializing a Struct of a Struct

If I have a struct in C that has an integer and an array, how do I initialize the integer to 0 and the first element of the array to 0, if the struct is a member another struct so that for every instance of the other struct the integer and the array has those initialized values?
Initialisers can be nested for nested structs, e.g.
typedef struct {
int j;
} Foo;
typedef struct {
int i;
Foo f;
} Bar;
Bar b = { 0, { 0 } };
I hope this sample program helps....
#include <stdio.h>
typedef struct
{
int a;
int b[10];
}xx;
typedef struct
{
xx x1;
char b;
}yy;
int main()
{
yy zz = {{0, {1,2,3}}, 'A'};
printf("\n %d %d %d %c\n", zz.x1.a, zz.x1.b[0], zz.x1.b[1], zz.b);
return 0;
}
yy zz = {{0, {0}}, 'A'}; will initialize all the elements of array b[10] will be set to 0.
Like #unwind suggestion, In C all instances created should initialized manually. No constructor kind of mechanism here.
You can 0-initialize the whole struct with {0}.
For example:
typedef struct {
char myStr[5];
} Foo;
typedef struct {
Foo f;
} Bar;
Bar b = {0}; // this line initializes all members of b to 0, including all characters in myStr.
C doesn't have constructors, so unless you are using an initializer expression in every case, i.e. write something like
my_big_struct = { { 0, 0 } };
to initialize the inner structure, you're going to have to add a function and make sure it's called in all cases where the structure is "instantiated":
my_big_struct a;
init_inner_struct(&a.inner_struct);
Here is an alternative example how you would do things like this with object-oriented design. Please note that this example uses runtime initialization.
mystruct.h
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
typedef struct mystruct_t mystruct_t; // "opaque" type
const mystruct_t* mystruct_construct (void);
void mystruct_print (const mystruct_t* my);
void mystruct_destruct (const mystruct_t* my);
#endif
mystruct.c
#include "mystruct.h"
#include <stdlib.h>
#include <stdio.h>
struct mystruct_t // implementation of opaque type
{
int x; // private variable
int y; // private variable
};
const mystruct_t* mystruct_construct (void)
{
mystruct_t* my = malloc(sizeof(mystruct_t));
if(my == NULL)
{
; // error handling needs to be implemented
}
my->x = 1;
my->y = 2;
return my;
}
void mystruct_print (const mystruct_t* my)
{
printf("%d %d\n", my->x, my->y);
}
void mystruct_destruct (const mystruct_t* my)
{
free( (void*)my );
}
main.c
int main (void)
{
const mystruct_t* x = mystruct_construct();
mystruct_print(x);
mystruct_destruct(x);
return 0;
}
You don't necessarily need to use malloc, you can use a private, statically allocated memory pool as well.

Passing addresses to functions in C

I'm new to C and I have a function that calculates a few variables. But for now let's simplify things. What I want is to have a function that "returns" multiple variables. Though as I understand it, you can only return one variable in C. So I was told you can pass the address of a variable and do it that way. This is how far I got and I was wondering I could have a hand. I'm getting a fair bit of errors regarding C90 forbidden stuff etc. I'm almost positive it's my syntax.
Say this is my main function:
void func(int*, int*);
int main()
{
int x, y;
func(&x, &y);
printf("Value of x is: %d\n", x);
printf("Value of y is: %d\n", y);
return 0;
}
void func(int* x, int* y)
{
x = 5;
y = 5;
}
This is essentially the structure that I'm working with. Could anyone give me a hand here?
You should use *variable to refer to what a pointer points to:
*x = 5;
*y = 5;
What you are currently doing is to set the pointer to address 5. You may get away with crappy old compilers, but a good compiler will detect a type mismatch in assigning an int to an int* variable and will not let you do it without an explicit cast.
void function(int *x, int* y) {
*x = 5;
*y = 5;
}
would change the values of the parameters.
In addition to the changes that the other posters have suggested for your function body, change your prototype to void func(int *,int *), and change your function definition (beneath main) to reflect void as well. When you don't specify a return type, the compiler thinks you are trying to imply an int return.
You can't forward declare func(int,int) when in reality it is func(int*, int*). Moreover, what should the return type of func be? Since it doesn't use return, I'd suggest using void func(int*, int*).
You can return a single variable of a struct type.
#include <stdio.h>
#include <string.h>
struct Multi {
int anint;
double adouble;
char astring[200];
};
struct Multi fxfoo(int parm) {
struct Multi retval = {0};
if (parm != 0) {
retval.anint = parm;
retval.adouble = parm;
retval.astring[0] = parm;
}
return retval;
}
int main(void) {
struct Multi xx;
if (fxfoo(0).adouble <= 0) printf("ok\n");
xx = fxfoo(42);
if (strcmp(xx.astring, "\x2a") == 0) printf("ok\n");
return 0;
}

Resources