Home > Back-end >  C how to use "operator new" keyword instead of C malloc()?
C how to use "operator new" keyword instead of C malloc()?

Time:11-05

StackMeta_t *mystack_create(size_t objsize)
{
  StackMeta_t *elem;
  elem = (StackMeta_t*)malloc(sizeof(StackMeta_t));
    if(elem == NULL)
    {
      return NULL;
    }
    else
    {
      elem->stack = NULL; // my actual stack basically the first elem(the top)
      elem->objsize = objsize;  // size of the datatype
      elem->numelem = 0;        // total count of elem inside the stack
    }
    return elem;
}

//PUSH
int mystack_push(StackMeta_t *data_stack, void* obj)
{
    if(data_stack == NULL)
    {
      return -1;
    }
    
    StackObject_t *nodeObject = NULL;
    nodeObject = (StackObject_t*)malloc(sizeof(StackObject_t));
    if(nodeObject == NULL)
    {
      return -1;
    }
    
    nodeObject->obj = malloc(data_stack->objsize);
    if(data_stack->stack == NULL)
    {
      nodeObject->next = NULL;
    }
    else
    {
      nodeObject->next = data_stack->stack;   
    }
    memcpy(nodeObject->obj, obj, data_stack->objsize);
    data_stack->stack = nodeObject;
    data_stack->numelem  ;

    return 0;
}

So I am trying to translate my C code into C code. These are Linked List and Stacks data structure

I researched that the malloc() version of C is the new keyword. So creating memory for the linked list nodeObject, I did StackObject_t *nodeObject = new StackObject_t;.

But the problem I encountered is creating memory for the obj of the Linked List. The data type for this variable is void* obj;. So that would be using a pointer to the objsize created with by the mystack_create(size_t objsize) function.

My question is, how do I convert nodeObject->obj = malloc(data_stack->objsize); to C while using the new keyword?

I tried doing nodeObject->obj = new data_stack->objsize; and the error gives me expected a type specifier. Do I need to cast data_stack->objsize? and what is the syntax for this for future reference? I have been coding with C for almost a year now and I know a few OOP from C#. Now I am just beginning to learn C and I couldn't find any answer for this type of situation.

CodePudding user response:

You should probably not use void* in C - it's usually not a good idea to abandon the type system. Instead, use templates.

So instead of doing

struct StackMeta_t
{
   //stuff
   void* obj;
};

just do

template <class T>
struct StackMeta_t
{
   //stuff
   T* obj;
};

Whatever type you put as T is what controls the typing of obj; for example, StackMeta_t<int> would result in int* obj;, etc, unless you'd rather change the typing of obj halfway through your program, which is probably something you would not want to do anyways.

Also just use std::stack if you want to use a stack in C .

CodePudding user response:

If your goal is to use C instead of the old C methods, then you should go all the way and use the current guidelines. The current way to use pointers and memory management is through smart pointers.

The reason these are useful, especially for your case, is because they do both the memory management for you (allocation and de-allocation) and prevent memory leaks or "read-after-free" kind of bugs.

I did a simple implementation of your stack object using std::shared_ptr, which is appropriate in your case as you want to reference an external object in your obj* member.

struct StackObject
{
    StackObject(void* p_obj)
    {
        obj = p_obj;
    }
    void* obj;
    std::shared_ptr<StackObject> next;
};

struct StackMeta
{
    int numelem;
    size_t objsize;
    std::shared_ptr<StackObject> stack; // First object

    StackMeta(size_t p_objsize)
    {
        objsize = p_objsize;
        stack = nullptr;
        numelem = 0;
    }

    void push(void* obj)
    {
        std::shared_ptr<StackObject> newobj = std::make_shared<StackObject>(obj);
        newobj->next = stack;
        stack = newobj; // make the stack reference the newly created object
        numelem  ;
    }
};

For this to function, you need to include memory. To test this, I made a simple main():


int main()
{
    StackMeta list(4); // 4 bytes for integers

    int some_int1 = 48;
    int some_int2 = 480;
    int some_int3 = 148;
    int some_int4 = 408;

    list.push(&some_int1);
    list.push(&some_int2);
    list.push(&some_int3);
    list.push(&some_int4);

    StackObject* curr_obj_ptr = list.stack.get();
    while(curr_obj_ptr != nullptr)
    {
        int curr_obj = *(reinterpret_cast<int*>(curr_obj_ptr->obj));
        std::cout << "Current object: " << curr_obj << std::endl;
        curr_obj_ptr = curr_obj_ptr->next.get();
    }

    return 0;
}

Which prints:

Current object: 408
Current object: 148
Current object: 480
Current object: 48

Please correct me if I misunderstood your implementation.

A final note: It is a very bad practice to use void* in C . In our case, it forced us to call a reinterpret_cast which is not desirable. The correct approach is to use a template for the StackMeta and StackObject classes.

  • Related