1

I am trying to implement a java like arraylist in C and now I am trying to make it generic. I am new to C and pointer arithmetic but I triedusing void* pointer for container, then element size(for size of data type), capacity and size. Currently in my add method I am getting an error saying (expression must have struct or union type in the add method inside of memcpy). As I understand memcpy, the first parameter is the destination where i want to put my input so i iterate from start of my container to elementSize*numElements ahead to reach the last index to append my input. Then the third parameter is the size of input. And is the resize function alright? I am new to C and playing around for educational purposes and any help is appreciated. Thank you

_____________________________________________________________________________________________
#ifndef ARRAYLIST_H
#define ARRAYLIST_H

typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
    void *con;
    int elementSize;
    int numElements;
    int conSize;
};

ArrayList *createArrayList();
void freeArrayList(ArrayList *);
void add(ArrayList *, void*);

#endif
___________________________________________________________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include "ArrayList.h"
#define CAPACITY 5
ArrayList *createArrayList(int elementSize) {
    ArrayList *arrayList = malloc(sizeof(ArrayList));
    arrayList->elementSize = elementSize;
    arrayList->conSize = CAPACITY;
    arrayList->numElements = 0;
    arrayList->con = malloc(sizeof(elementSize) * CAPACITY);
    return arrayList;
}

void freeArrayList(ArrayList * arrayList) {
    if (arrayList == NULL) {
        return;
    }else {
        free(arrayList->con);
        free(arrayList);
    }
}
void add(ArrayList *list, void *input) {
    if (list->numElements >= list->conSize) {
        resize(list);
        printf("resized\n");
    }
    memcpy(list->con + (list.numElements) * (list.elementSize), input, list->elementSize * list->numElements);
    list->numElements++;
}

void resize(ArrayList *list) {
    void *temp = realloc(list->con, (list->conSize + 100) * list->elementSize);
    if (temp != NULL) {
        list->conSize += 100;
        list->con = temp;
    }
}
  • Does this answer your question? [Pointer arithmetic for void pointer in C](https://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c) – kaylum May 01 '20 at 00:02
  • Try: `(char *)list->con + (list.numElements) * (list.elementSize)` – kaylum May 01 '20 at 00:03
  • No doesnt work. @kaylum – user13443636 May 01 '20 at 00:12
  • Care to expand on "doesn't work"? What did you change exactly and what errors did you get? – kaylum May 01 '20 at 00:13
  • i added the cast and got the same expression must have struct or union type error – user13443636 May 01 '20 at 00:16
  • Can you please paste the exact error into the question? – kaylum May 01 '20 at 00:19
  • `arrayList->con = malloc(sizeof(elementSize) * CAPACITY);` is wrong. That `sizeof` doesn't belong there it should simply be `arrayList->con = malloc(elementSize * CAPACITY);` And fyi, don't do pointer arithmetic with `void*`. Use a properly typed pointer (likely `unsigned char*` or including `stdint.h` and using `uint8_t *` – WhozCraig May 01 '20 at 00:34

1 Answers1

2

It looks like you're pretty close, but there were some issues with your add function.

Since list is a pointer you need list->numElements not list.numElements and the same for list->elementSize. Also since you are only inserting one element, the third argument to memcpy should just be list->elementSize.

void add(ArrayList *list, void *input) {
    if (list->numElements >= list->conSize) {
        resize(list);
        printf("resized\n");
    }
    memcpy((char*)list->con + list->numElements * list->elementSize, input, list->elementSize);
    list->numElements++;
}

The resize function looks almost correct, except that if realloc fails it just returns. It should probably either error out or return a value indicating an error to the caller.

idz
  • 12,825
  • 1
  • 29
  • 40
  • Thank you so much @idz. However I am getting an error saying expression must be a pointer to a acomplete object type under list->con in memcpy ? – user13443636 May 01 '20 at 00:40
  • Oh, I missed that. That's because `list->con` is `void*` and so the compiler does not know what size what it's pointing to is. The solution is to cast it to a `(char *)`. I'll update the answer in a few minutes. – idz May 01 '20 at 00:51