glib how address to index g_ptr_array - c

I have 3 structures and I use GNOME glib library to have dynamic array.
typedef struct Neuron
{
//number of inputs into neuron
int NumInputs;
//growing array of weights for each input
GArray* ArrWeight;
}neuron;
typedef struct NeuronLayer
{
//number of neurons in layer
int NumNeurons;
//growing array of neurons
GPtrArray* ArrNeurons;
}layer;
typedef struct Net
{
int numInputs;
int numOutputs;
int numHiddenLayers;
int NeuronsPerHiddenLayer;
//each layer of neurons
GPtrArray* ArrLayers;
}net;
I want write cycle like that
for (k = 0; k < Net->ArrLayers->pdata[i].ArrNeuron->pdata[j].NumInputs; k++)
But I dont know how address to array. Compiler (clang say) :
member reference base type 'gpointer' (aka 'void *') is not
a structure or union.
structure of Gptrarray:
struct GPtrArray
{
gpointer *pdata;
guint len;
};
I think i should write something like that
Net->ArrLayers->pdata[i*sizeof(layer)].ArrNeurons->pdata[j*sizeof(neuron)].NumInputs

gpointer is a generic pointer. You are using it to store a pointer of a specific type. So to access its elements you must use a type cast.
I will first try to break your statement down. It currently looks like this:
Net->ArrLayers->pdata[i].ArrNeuron->pdata[j].NumInputs
I assume Net is a variable of type net *.
Net->ArrLayers is of type GPtrArray *.
Net->ArrLayers->pdata is of type gpointer *, i.e. void **, a pointer to a pointer.
Net->ArrLayers->pdata[i] is thus of type gpointer, i.e. void *, a pointer.
Now you want to access its element. Judging from your context, you want to interpret this pointer as a pointer to layer. However, the compiler doesn't know that. You need to tell the compiler.
So you should add a cast, (layer *)Net->ArrLayers->pdata[i].
Now since this is of type layer * and not layer, you still need -> instead of . to access its element, so it should now become:
((layer *)Net->ArrLayers->pdata[i])->ArrNeuron
Now you need to access pdata again. This is the same as the above, so I'll skip the explanation and show you the correct method:
((neuron *)((layer *)Net->ArrLayers->pdata[i])->ArrNeuron->pdata[j])->NumInputs
As you can see this is very messy. It would be better to split this into several statements to enhance readability, and by doing so you may even skip the casts:
int current_num_inputs(net * Net, size_t i, size_t j) {
layer *current_layer = Net->ArrLayers->pdata[i];
neuron *current_neuron = current_layer->ArrNeuron->pdata[j];
return current_neuron->NumInputs;
}
Then in your for loop:
for(k = 0; k < current_num_inputs(Net, i, j); k++) { // ...

Related

Pointer inside a structure not changing when passing by reference C

So, I'm pretty new to the C language and I've been passed a project by my professor to make a game in C. My problem is, I created a structure like so:
typedef struct vector
{
int parts;
int dir;
} Vector;
typedef struct snake
{
Vector* parts;
Vector dir;
} Snake;
I'm trying to initialize the parts pointer within this function:
void init_snake(struct snake *snake, int size, int x, int y)
{
snake->parts = (Vector *)malloc(sizeof(Vector) * size);
for (int i = 0; i < size; i++)
{
//sets the body parts one after the other in a line
snake->parts[i].x = x - i * PIXEL_SIZE;
snake->parts[i].y = y;
}
//sets the snake direction to the left
snake->dir.x = 1;
snake->dir.y = 0;
}
But by doing that the array parts inside the snake pointer is not initialized as expected. By checking its size with sizeof(snake.parts) / sizeof(Vector) it returns 0. Any ideas of how to fix it?
It likely is working, you're just confused about sizeof. This operator measures the size (in bytes) of a type. If you ask for the size of a value, it uses the type of that expression instead.
This is a compile-time evaluation and therefore is not dynamic.
sizeof(snake.parts) is the same as sizeof(Vector*) which will be either 4 or 8 bytes depending on whether you are compiling to a 32-bit or 64-bit target. Therefore, it's not useful to determine the size of an allocation.
Generally, given a pointer, you cannot tell how large the allocation is. Usually this is handled by storing some kind of useful length somewhere else. For example, you could modify struct snake to include an element count for parts:
typedef struct snake
{
Vector* parts;
int parts_size;
Vector dir;
} Snake;
And set this value accordingly:
snake->parts = (Vector *)malloc(sizeof(Vector) * size);
snake->parts_size = size;

Possible side effects of doing a typedef of a struct to an array of one element in C

I came across this code.
typedef __mpz_struct MP_INT;
typedef __mpz_struct mpz_t[1];
Here the struct __mpz_struct is a struct that is typedefed to an array of single element. I understand that this is a trick to pass by reference in C. Then mpz_t has been used as a type to declare variables and pass them to function as parameters. Also, There was one more comment
/*
MP_INT*, MP_RAT* and MP_FLOAT* are used because they don't have side-effects
of single-element arrays mp*_t
*/
What kind of side effects are they talking about?
Passing an array to a function let's the array decay to a pointer to it's 1st element.
One can achieve the same effect by applying the Address-Of operator & to a simple variable of the same type as the array's elements.
Examples:
struct S
{
int i;
float f;
};
This
void set_S(struct S * ps)
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps->i = 40;
ps->f = 2.;
}
is equivalent to
void set_S(struct S * ps)
{
ps[0].i = 40;
ps[0].f = 2.;
}
is equivalent to
void set_S(struct S ps[1])
{
ps[0].i = 40;
ps[0].f = 2.;
}
One-Element-Array approach:
typedef struct S Array_of_S_with_size_1[1];
int main(void)
{
Array_of_S_with_size_1 array_of_S_with_size_1;
array_of_S_with_size_1[0].i = 0;
array_of_S_with_size_1[0].f = 0.;
set_S(array_of_S_with_size_1);
...
}
The above main() provides the same functionality as the following:
int main(void)
{
struct S s;
s.i = 0;
s.f = 0.;
set_S(&s);
...
}
I do not see any gain using the "One-Element-Array" approach. An expection might be if the &-key is broken on ones keyboard ... ;-)
I see two parts to your question. The first part, how the typedef works for passing arguments to functions, would better be illustrated with an example. Without it, I'll have to guess a bit.
In C function declarations, an array parameter is equivalent to a pointer. That's why you see (for example) equivalently for the main function,
int main(int argc, char **argv)
and
int main(int argc, char *argv[])
Similarly, if a function in your program would be declared
int func(__mpz_struct *arg)
it would be equivalent to
int func(__mpz_struct arg[])
and hence to
int func(mpz_t arg)
Also, on the calling side, if you have a variable of type mpz_t, hence the array, and you pass it to a function, the "pointer decay" takes effect: in an expression, if you use (the name of) an array it "decays" into a pointer to its first element.
This way you can call the function:
mpz_t value;
func(value);
Of course, to modify these mpz_t objects outside of the API functions, you still have to be aware of their true nature.
The side effects that you mention, I would also have to guess about them. Possibly it is meant that you have to be aware you're working with pointers inside the functions. It might be considered better to make that explicit by using the pointer syntax.
You can assign an MP_INT to another but you can not assign an mpz_t to another since assignment is not defined for arrays. If you do not want your clients to assign variables other than by your methods (which might do memory managements and stuff) this is the trick for you.
Look at this sample code
typedef char type24[3];
Same as your, but well known data type 'char' insted of your struct __mpz_struct type.
above type def means, I am using above typedef to represent char[3].
So in your sample code,
typedef __mpz_struct mpz_t[1];
mpz_t should be __mpz_struct type.

Kind of polymorphism in C

I'm writing a C program in which I define two types:
typedef struct {
uint8_t array[32];
/* struct A's members */
...
} A;
typedef struct {
uint8_t array[32];
/* struct B's members, different from A's */
...
} B;
Now I would like to build a data structure which is capable of managing both types without having to write one for type A and one for type B, assuming that both have a uint8_t [32] as their first member.
I read how to implement a sort of polymorphism in C here and I also read here that the order of struct members is guaranteed to be kept by the compiler as written by the programmer.
I came up with the following idea, what if I define the following structure:
typedef struct {
uint8_t array[32];
} Element;
and define a data structure which only deals with data that have type Element? Would it be safe to do something like:
void f(Element * e){
int i;
for(i = 0; i < 32; i++) do_something(e->array[i]);
}
...
A a;
B b;
...
f(((Element *)&a));
...
f(((Element *)&b));
At a first glance it looks unclean, but I was wondering whether there are any guarantees that it will not break?
If array is always the first in your struct, you can simply access it by casting pointers. There is no need for a struct Element. You data structure can store void pointers.
typedef struct {
char array[32];
} A;
typedef struct {
void* elements;
size_t elementSize;
size_t num;
} Vector;
char* getArrayPtr(Vector* v, int i) {
return (char*)(v->elements) + v->elementSize*i;
}
int main()
{
A* pa = malloc(10*sizeof(A));
pa[3].array[0] = 's';
Vector v;
v.elements = pa;
v.num = 10;
v.elementSize = sizeof(A);
printf("%s\n", getArrayPtr(&v, 3));
}
but why not have a function that works with the array directly
void f(uint8_t array[32]){
int i;
for(i = 0; i < 32; i++) do_something(array[i]);
}
and call it like this
f(a.array)
f(b.array)
polymorphism makes sense when you want to kepp
a and b in a container of some sorts
and you want to iterate over them but you dont want to care that they are different types.
This should work fine if you, you know, don't make any mistakes. A pointer to the A struct can be cast to a pointer to the element struct, and so long as they have a common prefix, access to the common members will work just fine.
A pointer to the A struct, which is then cast to a pointer to the element struct can also be cast back to a pointer to the A struct without any problems. If element struct was not originally an A struct, then casting the pointer back to A will be undefined behavior. And this you will need to manage manually.
One gotcha (that I've run into) is, gcc will also allow you to cast the struct back and forth (not just pointer to struct) and this is not supported by the C standard. It will appear to work fine until your (my) friend tries to port the code to a different compiler (suncc) at which point it will break. Or rather, it won't even compile.

union types and flexible array member

I have a question about the flexible-length arrays in C structures (http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html).
typedef struct {
size_t N;
int elems[];
} A_t;
Now the general approach is quite obvious,
A_t * a = malloc(sizeof(A_t) + sizeof(int) * N)
a->N = N;
....
Now this seems to be awkward when trying to incorporate stuff into other structs or stack-based allocation. So something like the following snipet is bound to fail for N!=0
struct {
A_t a;
A_t b; /// !!!!!
double c; /// !!!!!
};
Now I think it should be possible to allow for usages like this by defining another type
typedef struct {
size_t N;
int elems[5];
} A_5_t;
struct {
A_5_t a;
A_5_t b;
double c; // should work here now.
} mystruct;
and then use it as if it were an A_t structure. When calling a function void foo(A_t * arg1);, one would need to use something like foo((A_t*) (&mystruct.b)). Which -- to me -- appears to be a bit clumsy. I therefore wonder whether there is a better way to do this. I wonder whether one could employ a union type for this somehow?
I am asking this question, because the flexible-length array makes it possible to have data in one piece in the structure, therefore one can copy a struct with a single command instead of having to worry about deep and shallow copies, etc.
You have a mult-layered question.
In this one example:
struct {
A_t b;
double c; /// fails
};
I would try:
struct {
double c;
A_t b;
};
Always place the variable portion of a struct at the end. Note, I don't use GCC, so try this, it might/maybe work.
To follow-up on a requirement given by #wirrbel, the following struct is NOT variable length, but it does define and provide access to a variable length array of integers.
typedef struct {
size_t N;
int *(elems[]); // parens to ensure a pointer to an array
} A_t;
A_t *a = malloc //etc.
a->elems = malloc(sizeof(int) * N);
In this fashion several A_t structures can be included in a more general structure.
No, in general your two struct, A_t and A_5_t, are not interchangeable. The reason is that the version with the flexible array can have different padding in front of the elems field than versions with a fixed field length.
Whether or not your compiler implements a different padding or not, you can test by using the offsetof macro. But even if the offsets are the same for your particular compiler and platform, you'd better not rely on that if you want portable code.
I have figured it out now (the solution has actually been descibed in the gnu documentation as provided above). By appending an array declaration after the struct declaration, one does create a contiguous memory range that is directly adjacent to the "empty" flexible array. Therefore b.A.elems[i] is referencing the same data as b.elems_[i].
It is probably advisable to choose an identifier that tells you that the memory of this array is actually belonging to the structure. at least thats how I would use it then.
typedef struct {
size_t N;
double elems[];
} A_t;
typedef struct {
A_t a;
double elems_[4];
} B_t;
void foo(A_t * arg1) {
for (size_t i=0; i < arg1->N; ++i) {
printf("%f\n", arg1->elems[i]);
}
}
int main(int argc, char *argv[]) {
B_t b;
b.a.N = 4;
for (int i=0; i < 4; ++i) {
b.elems_[i] = 12.4;
}
foo(&b.a);
}

How do I have a variable in C that can accept various types?

I'm looking to implement a dictionary data structure in C which I want to be as generic as possible. That is to say it can accept a pair of values that can be of any type.
How can I init a variable that can accept any types?
And how can I convert that type back to a type I want? (Typecast)
Thanks.
The way to define a variable that can hold values of more than one type is to use unions:
union uu {
int i;
float f;
char c;
char *s;
} x;
x.i is an integer, x.s a char pointer etc. and the size of x is the maximum among the sizes of the members type.
Unfortunately the only way to remember the type of the variable is to store it somewhere else. A common solution is to have a structure like this:
struct ss {
int type;
union {
int i;
float f;
char c;
char *s;
} val;
} x;
And do something like:
#define FLOAT 1
#define INT 2
....
x.val.i = 12;
x.type = INT;
....
if (x.type = INT) printf("%d\n",x.val.i);
....
really ugly.
There are other possibility playing with the macro processor to make it a little bit more pleasent to the eye but the essence is that you have to know in advance the type of the value stored in the union and access the proper field.
This isn't trivial to do, but here's the simplest way to do it:
You need to know all the types you'll support, and what they are when you insert them.
First, you'll actually have a data structure of some struct like
struct { void * data; enum Type tag }
and define an enum Type { int, char*, ... etc }
The void * is a pointer to data without a type, so you can use it to store to a chunk of memory that contains the data you want to store.
The Type tag stores what the data is so that your code using it can know what is being returned from your data structure.
If you don't need to store the type, and you can cast it back to the correct type when you pull it out of your data structure, then you can omit the Type tag and just store void *
In C there is no easy way to do this. You can use void* and pass around pointers to the types, but there is no concept of templates or generics or variants that exists.
To use void* you would need to treat everything as a pointer so would have to allocate it on the heap. You would then need to cast those pointers to void* when sending to this data structure and then cast back on the other side. This can be tricky because you have to remember what the types were to start with.
If you happen to be programming on Windows you can use Variants to do this, but there is some overhead associated with it.
You probably want void *.
You've got two options:
void* foo;
which can point to data of any type, or:
union my_types {
int* i;
char* s;
double* d;
bool* b;
void* other;
}
which gives you "automatic" pointer casting (in that you can reference a variable of type "my_types" as if it were any of the above types). See this link for more on unions.
Neither is a great option -- consider C++ for what you're trying to do.
Use a void * ?
You can typecast to whatever you want provided of course you must perform the checking yourself.
Your solution will have to use pointers to void.
Pointers to void can hold the address of any object type (not functions) and can be converted back without loss of information.
Best is to use a "parent structure" so that you know the type of the object pointer to:
enum MyType { INTEGER, DOUBLE_STAR };
struct anytype {
enum MyType mytype;
size_t mysize;
void *myaddress;
};
and then
struct anytype any_1, any_2;
int num_chars;
double array[100];
any_1.mytype = INTEGER;
any_1.myaddress = &num_chars;
any_1.mysize = sizeof num_chars;
any_2.mytype = DOUBLE_STAR;
any_2.myaddress = array;
any_2.size = sizeof array;
and, to work with that
foo(any_1);
foo(any_2);
where foo is defined as
void foo(struct anytype thing) {
if (thing.mytype == INTEGER) {
int *x = thing.myaddress;
printf("the integer is %d\n", *x);
}
if (thing.mytype == DOUBLE_STAR) {
size_t k;
double *x = thing.myaddress;
double sum = 0;
for (k = 0; k < thing.mysize; k++) {
sum += thing.myaddress[k];
}
printf("sum of array: %f\n", sum);
}
}
CODE NOT TESTED
You can use a void * pointer to accept a pointer to pretty much anything. Casting back to the type you want is the tricky part: you have to store the type information about the pointer somewhere.
One thing you could do is use a struct to store both the void * pointer and the type information, and add that to your data structure. The major problem there is the type information itself; C doesn't include any sort of type reflection, so you'll probably have to create an enumeration of types or store a string describing the type. You would then have to force the user of the struct to cast back from the void * to the original type by querying the type information.
Not an ideal situation. A much better solution would probably be to just move to C++ or even C# or Java.
enum _myType { CHAR, INT, FLOAT, ... }myType;
struct MyNewType
{
void * val;
myType type;
}
Then you could pass elements of type MyNewType to your functions. Check the type and perform the proper casting.
C offers unions which may suit your purposes, you need to define all the types before compilation but the same variable can point to all the types you include in the union.

Resources