0
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.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
Heroking18
  • 77
  • 6
  • 1
    The common syntax is: `Object * pointer_to_object = new Object;`. – Thomas Matthews Nov 04 '22 at 23:16
  • 5
    C and C++ are two completely different languages. Translating from C to C++, one statement at a time, always ends in tears. The only way to learn C++, that's required in order to understand C++ and figure out how to correctly translate from C to C++, is [with a good C++ textbook](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). Unfortunately, Stackoverflow is not a replacement for a C++ textbook, and C++ is too complicated to be learned by asking one question at a time; a C++ textbook is required. – Sam Varshavchik Nov 04 '22 at 23:18
  • also, just use std::stack, and don't use memset – Neil Butterworth Nov 04 '22 at 23:26
  • post the original `C` code and the actual `C++` stuff as it is now. And translate the data structure not the program in the first place. (I believe you know that STL provides this and more data strucutres, called __contianers__ in ``C++` and you can replicate that – arfneto Nov 04 '22 at 23:31
  • 1
    When allocating more than one instance, use `std::vector`. Syntax: `std::vector database;`. – Thomas Matthews Nov 04 '22 at 23:31
  • Even though your question involves C, it is not about C, and tagging it with C is not very helpful—people who are following the C tag but are not interested in the C++ tag might not be able to help much, and people in the future using the C tag to search for questions about C issues will not be helped by finding this one. So I am removing the C tag. – Eric Postpischil Nov 04 '22 at 23:53
  • Back around 2008 I figured that a C++ course I took in the mid'90s and 20 years of Java and C meant I knew C++. Holy was I wrong. I am still finding, cringing over, and replacing as quietly as possible code I wrote between 2008 and 2012. [Get a good book or two](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). You know C, so you won't have to start with one of the See Spot Code variety, but I cannot stress enough: Get a good book. Then read through some of the Scott Meyers *Effective * books to fill in the blanks. – user4581301 Nov 05 '22 at 00:40
  • *So I am trying to translate my C code into C++ code.* -- *These are Linked List* -- `std::list` -- *and Stacks* -- `std::stack`. Work with those. Not only will your code have less bugs, you get to actually learn how this is done in C++. Also, I am assuming you know how to write a stack and linked list class already, so why waste time doing it all over again form scratch? – PaulMcKenzie Nov 05 '22 at 03:19

2 Answers2

1

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++.

1

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.

  • In case you're interested, here's an implementation of the `pop` function: ```c void* pop(){void* obj = stack->obj;stack = stack->next;numelem--;return obj;} ``` – Najmaoui Yassir Nov 05 '22 at 01:37