1

i have a function called create() that return a pointer to a struct named ann as shown below

typedef struct ann {
    int inputs;                 /* Number of input neurones      */
    int hidden_layers;          /* Number of hidden layers       */
    int hidden;                 /* Number of hidden neurones     */
    int outputs;                /* Number of output neurons.     */
    int weights;                /* Total nof weigths(chromosomes)*/
    int neurons;                /* Total Number of neurones      */
    double *weight;             /* The weights(genotype)         */
    double *output;             /* Output                        */
    double fitness;              /* Total fitness of the network    */
    double *delta;
    actfun activation_hidden;   /* Hidden layer activation func  */
    actfun activation_output;   /* Output layer activation func  */
} ann;

prototype of the function create()

ann *create(int inputs, int hidden_layers, int hidden, int outputs);

i need an array of ann s, so i have the following

int population_size = 10;
ann *population = malloc ( population_size * sizeof(ann));

    for( i = 0; i < population_size; i++ ){
        population[i] = create( trainset->num_inputs, 1 , hidden, trainset->num_outputs);
    }

but i am getting the following error

error: incompatible types when assigning to type ‘ann {aka struct ann}’ from type ‘ann * {aka struct ann *}’

My Question is how to type cast the current element in population so that the returned struct (a pointer) ann can be stored in population

As requested here is the full code of the function create()

ann *create   ( int inputs, int hidden_layers, int hidden, int outputs ) {

    if (hidden_layers < 0) return 0;
    if (inputs < 1) return 0;
    if (outputs < 1) return 0;
    if (hidden_layers > 0 && hidden < 1) return 0;


    const int hidden_weights = hidden_layers ? (inputs+1) * hidden + (hidden_layers-1) * (hidden+1) * hidden : 0;
    const int output_weights = (hidden_layers ? (hidden+1) : (inputs+1)) * outputs;
    const int total_weights = (hidden_weights + output_weights);

    const int total_neurons = (inputs + hidden * hidden_layers + outputs);

    /* Allocate extra size for weights, outputs, and deltas. */
    const int size = sizeof(ann) + sizeof(double) * (total_weights + total_neurons + (total_neurons - inputs));
    ann *ret = malloc(size);
    if (!ret) return 0;

    ret->inputs = inputs;
    ret->hidden_layers = hidden_layers;
    ret->hidden = hidden;
    ret->outputs = outputs;

    ret->weights = total_weights;
    ret->neurons = total_neurons;

    /* Set pointers. */
    ret->weight = (double*)((char*)ret + sizeof(ann));
    ret->output = ret->weight + ret->weights;
    ret->delta = ret->output + ret->neurons;

    ann_randomize(ret);

    ret->activation_hidden = ann_act_sigmoid_cached;
    ret->activation_output = ann_act_sigmoid_cached;

    ann_init_sigmoid_lookup(ret);

    return ret;
}
4
  • Don't return a pointer, return the structure. Commented Jan 5, 2020 at 20:56
  • Either that, or make it an array of pointers instead of an array of structures. Commented Jan 5, 2020 at 20:57
  • @Barmar how to do that, please help i am new to c Commented Jan 5, 2020 at 20:58
  • I'm on @Barmar side. But with an array of pointer you will have to move in create () the dynamic allocation (which is IMHO more correct). Commented Jan 5, 2020 at 21:03

4 Answers 4

3

The error

error: incompatible types when assigning to type ‘ann {aka struct ann}’ from type ‘ann * {aka struct ann *}

occurs because population[i] is a struct ann, not a pointer to it. Different types!

What you need to do, as already stated by Stephan Lechner's answer, is either change the array outside (making it an array of pointers) or the returned type of the create () function, making it return the structure itself.

What I'm going to suggest you is a change of create() interface in order to pass a pointer to it as a parameter the output structure to be populated.

In the caller function where the array of pointers to ann is defined:

ann *population[10] = { 0 };

for( i = 0; i < 10; i++ ){
    if ( create( &population[i], trainset->num_inputs, 1 , hidden, trainset->num_outputs) < 0 ){
        printf ("Issues during creation of ann #%d\n", i);
        break;
    }
} 

// Remember to free the pointers!

No allocation! It is moved inside create(), that will have two interface changes:

  1. The output pointer is passed as a parameter (the first, in my example)
  2. Returns an error code (0 on success, < 0 on failure)
int create(ann **outstruct, int inputs, int hidden_layers, int hidden, int outputs){
    int ret = 0;

    ann *tmp = malloc( sizeof(ann));

    // ...
    //do whatever you need to initialize the newly allocated struct

    // set ret to a negative value if anything goes wrong
    // ... but in this case free tmp before returning!
    //...

    outstruct = tmp;

    return ret;
}

In my example an ann ** pointer had to be passed to create() because it internally allocated the memory.

A simple pointer is enough if the structs are allocated externally and create() has just the role to populate it.

Sign up to request clarification or add additional context in comments.

7 Comments

You wrote this on a phone? How dare you! :P
I admit it. I had to fight with automatic corrections but I won (unless there are something I forgot to correct). :)
No. But it automatically puts spaces or capital letters. Something like If ( p == NULL). But is nothing special. It can be done; it is just slow. Feel free to give feedbacks on the technical contents of my answer. ;)
You can disable those. If you want to you can start a chatroom.
@RobertoCaboni It´s a real pain to write such detailed answer on a smartphone. I am personally not a big fan of the StackExchange Android App (many bugs etc.) nor of writing on smartphones in general. Huge respect for that.
|
2

You can either dereference the pointer before assigning like

population[i] = *create(...);

or you can change the prototype of your create-function to return a struct instead of a pointer to it:

ann create(int inputs, int hidden_layers, int hidden, int outputs);

The probably best way, however, would be - as suggested by Barmar - to use an array of pointers instead of an array of struct objects. A complete sample - not to be combined with the solutions provided above - could look as follows:

ann *create(int inputs, int hidden_layers, int hidden, int outputs) {
   ann* result = malloc (sizeof(ann));
   ..
   return result;
}

...

int population_size = 10;
ann **population = malloc ( population_size * sizeof(ann*));

for( i = 0; i < population_size; i++ ){
    population[i] = create( trainset->num_inputs, 1 , hidden, trainset->num_outputs);
} 

6 Comments

If the storage for the struct is allocated by malloc in create then population[i] = *create(...); will cause memory leak.
@Lxer Lx: the assignment is population[i] = create(...).
No! It is population[i] = *create(...); in the second line of your answer.
@Lxer Lx: the solutions are meant as separate alternatives, which cannot be mixed. Adapted the answer accordingly.
The first alternative will cause memory leak if the storage for the struct is allocated by malloc in create() because the pointer returned by malloc is dereferenced and lost forever. How can that pointer be reached after population[i] = *create(...); ? The struct object is copied but the pointer is lost and cannot be free()d before program termination.
|
1

An alternative to returning structures is to pass the address of the element as a parameter to the function.

ann **population = malloc (sizeof (ann *) * population_size);

for (i = 0; i < population_size; i++) {
    population[i] = malloc (sizeof (ann));
    create (population[i], trainset->num_inputs, 1 , hidden, trainset->num_outputs);
}

Then inside the function you can just assign the values to the pointer.

void create (ann *element, int inputs, int hidden_layers, int hidden, int outputs) {
     element->inputs = inputs;
     ...
}

Lastly, don't forget to free up unused memory space before terminating the program.

for (i = 0; i < population_size; i++) {
     free (population[i]);
}
free (population);

4 Comments

I wrote a really similar almost contemporarily, even if with a little difference. In my defence, I wrote it from my phone. :)
I like how you think :>
Your icon looks like mine... Coincidence?
I don't think so, but what do you mean mine looks like yours? Yours looks like mine :>
0

Abstracting from the program logic, you just need to dereference the result of the create and also save its return value for the free function to prevent the memory leak

ann *create(int inputs, int hidden_layers, int hidden, int outputs);

void foo()
{
int population_size = 10;
ann *population = malloc ( population_size * sizeof(ann));

    for( int i = 0; i < population_size; i++ )
    {
        ann *tempptr;
        population[i] = (tempptr = create( 1, 1 , 1, 1)) ? *tempptr : (ann){0,};
        free(tempptr);
    }
}  

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.