2

I am having trouble with the creating a dynArray and adding elements to it. I am not sure how to allocate memory for it. I have only recently started pointers so any help would be much appreciated.

typedef struct{
  doube *darray;
  int size;
}dynArray;//dynArray structure

dynArray *createDynArray(int n);
{
  dynArray *newdynArray;//newdynArray is a pointer to the dynArray structure
  newDynArray->darray=(double*)malloc(n*double);
6
  • 1
    You're derefencing an uninitialized variable newdynArray in the line with the malloc(); that's bad news. You first need to allocate something for the newdynArray to point at. Can you use C99 'flexible array members' (FAM)? If so, you do things one way; if not, you have to do things another way. Are you ready to learn about FAM or do you need to take time out learning basic pointers first — which is not unreasonable. Commented Dec 7, 2014 at 17:00
  • 1
    doube -> double and malloc(n*double) -> malloc(n*sizeof(double)) . More : someone will tell you not to cast the return of malloc(). See stackoverflow.com/questions/605845/… Commented Dec 7, 2014 at 17:01
  • Hi Jonathan I would prefer to get my head around pointers first. I am not sure where I am dereferencing a uninitialized pointer. I thought newdynArray is a pointer to dynArray and from this new pointer I can access darray to allocate memory for it? What is wrong with my logic Commented Dec 7, 2014 at 17:19
  • @Eamonn To which dynArray is newdynArray pointing? Commented Dec 7, 2014 at 17:23
  • newdynArray is pointing to dynArray structure. Commented Dec 7, 2014 at 17:25

4 Answers 4

1

You need to allocate space for both the container and the array itself:

typedef struct dynArray {
  double *darray;
  int size;
} dynArray;

dynArray *createDynArray(int n) {
    dynArray *newDynArray = malloc(sizeof(dynArray));
    newDynArray->size = n;
    newDynArray->darray = calloc(n, sizeof(double));
    return newDynArray;
}

void deleteDynArray(dynArray *dynArray) {
    free(dynArray->darray);
    free(dynArray);
}
Sign up to request clarification or add additional context in comments.

3 Comments

May be worth a short explanation about the use of calloc to allocate darray to insure all array values are initialized to 0 to protect against, among other things, inadvertent read from uninitialized space.
Hi Bill,thank you very much for your response. I just have one question how do you make sure there is enough memory. Do you need 2 check cases when using malloc and calloc or is there away of avoiding it and just using one.
@Eamonn: In the code above, I should be verifying that malloc() and calloc() don't return NULL. There is a common trick to reduce this to one allocation, which you can read about here: stackoverflow.com/questions/599365/… That being said, I would recommend using two allocations right now until you fully understand pointers.
0

You'd also need a function to do the freeing your allocation style can be made nicer without casts and using

typedef struct{
  double *darray;
  int size;
}dynArray;//dynArray structure

dynArray *createDynArray(int n)
{
  dynArray *newdynArray = malloc(sizeof *newdynArray); // don't cast the return
  // the below is called a compound literal (or composite literal)
  *newdynArray = (dynArray){malloc(n * (sizeof *newdynArray->darray)), n};
  return newdynArray;
}

void freeDynArray(dynArray *self)
{
  free(self->darray);    // free held data
  free(self);            // free the outer structure
}

As for adding elements, you could hide it behind functions, adding safety if you'd like

// return 0 on success, non-zero if error
int set_item(dynArray *self, int index, double e)
{
    if (index >= self->size || index < 0) { //bounds check
       return -1;
    }
    self->darray[index] = e;
    return 0;
}

double get_item(dynArray *self, int index)
{
    if (index >= self->size || index < 0) { //bounds check
        // Note: impossible to distinguish between error and actual 1.0
        return -1.0; 
    }
    return self->darray[index];
}

The bounds checks are of course up to you to decide. If you don't want them then remove them.

Comments

0

Another popular way to provide initializers and deinitializers for your structure is to only operate on already allocated memory. This approach is more general as it allows your structure to be used both, stack and heap allocated.

struct dynamic_array
{
  double * data;
  size_t size;
};

int
dynamic_array_init(struct dynamic_array *const dyn_arr_ptr,
                   const size_t size)
{
  if (dyn_arr_ptr == NULL)
    return -1;  /* invalid argument */
  /* Allocate an array initially filled with zeros. */
  dyn_arr_ptr->data = calloc(size, sizeof(double));
  if (dyn_arr_ptr->data == NULL)
    return -1;  /* out of memory */
  dyn_arr_ptr->size = size;
  return 0;  /* success */
}

int
dynamic_array_deinit(struct dynamic_array *const dyn_arr_ptr)
{
  if (dyn_arr_ptr == NULL)
    return 0;  /* nothing to do */
  free(dyn_arr_ptr->data);
  dyn_arr_ptr->data = NULL;
  dyn_arr_ptr->size = 0;
  return 0;
}

It can then be used to initialize a stack-based structure…

struct dynamic_array dyn_arr;
if (dynamic_array_init(&dyn_arr, 42) < 0)
  {
    fprintf(stderr, "error: cannot initialize array\n");
    return EXIT_FAILURE;
  }
/* Use the dynamic array... */
dynamic_array_deinit(&dyn_arr);

… as well as a heap-based one.

struct dynamic_array * dyn_arr_ptr = malloc(sizeof(struct dynamic_array));
if (dynamic_array_init(dyn_arr_ptr, 42) < 0)
  {
    fprintf(stderr, "error: cannot initialize array\n");
    return EXIT_FAILURE;
  }
/* Use the dynamic array... */
dynamic_array_deinit(dyn_arr_ptr);
free(dyn_arr_ptr);

Note that I can pass the result of malloc unchecked to the initializer function because it does a NULL check and handles this case gracefully.

Comments

0

I would include checking for NULL. Just in a case.

#include <stdio.h>
#include <stdlib.h>

typedef struct{
    double *darray;
    int size;
}dynArray;

dynArray *createDynArray(int n)
{
    dynArray *newdynArray = malloc(sizeof(dynArray));
    if (newdynArray!=NULL) newdynArray->darray=malloc(n*sizeof(double));
    newdynArray->size = n;
    return newdynArray;
} 

dynArray *deleteDynArray(dynArray *olddynArray) {
    if (olddynArray!=NULL) free(olddynArray->darray);
    free(olddynArray);
    return olddynArray;
}

int main() {
    int i;
    dynArray *my;
    my = createDynArray(10);
    if (my->darray!=NULL) {
        for (i=0; i<my->size; i++)
            my->darray[i] = (float)i;
        for (i=0; i<my->size; i++)
            printf("%lf\t", my->darray[i]);
    }
    deleteDynArray(my);
    return 0;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.