Week02 Lab Notes

ex1

Use of ++ and -- in array indexing.

Try to be careful abou that.

If you use it and cannot explain, it might be a trouble.

For example, if you use the following statement in your pop.

int val = ps->data[--size]

My suggestion is to STRONGLY avoid using these misleading expressions for beginners, especially in your Q&A.

strcmp

int strcmp (const char* str1, const char* str2);

Are there any alternatives to this beautiful code ?

    if (strcmp(token, "+") == 0 || strcmp(token, "-") == 0 || 
        strcmp(token, "*") == 0 || strcmp(token, "/") == 0)
    {
        int b = ps->pop(ps);
        int a = ps->pop(ps);

        if (strcmp(token, "+") == 0) ps->push(ps, a + b);
        else if (strcmp(token, "-") == 0) ps->push(ps, a - b);
        else if (strcmp(token, "*") == 0) ps->push(ps, a * b);
        else if (strcmp(token, "/") == 0) ps->push(ps, a / b);
    }
    else
    {
        ps->push(ps, atoi(token)); // Convert string to int and push onto stack
    }
    

or this

while (NULL != token)
  {
      if (strcmp(token, "+") == 0) {
          int num1 = ps->pop(ps);
          int num2 = ps->pop(ps);
          ps->push(ps, num2+num1);
      }
      else if (strcmp(token, "-") == 0) {
          int num1 = ps->pop(ps);
          int num2 = ps->pop(ps);
          ps->push(ps, num2-num1);
      }
      else if (strcmp(token, "*") == 0) {
          int num1 = ps->pop(ps);
          int num2 = ps->pop(ps);
          ps->push(ps, num2*num1);
      }
      else if (strcmp(token, "/") == 0) {
          int num1 = ps->pop(ps);
          int num2 = ps->pop(ps);
          ps->push(ps, num2/num1);
      }
      
      else {
          ps->push(ps, atoi(token));
      }

    // get next token
    token = strtok(NULL, delim);
  }

ex2

check if a pointer is NULL

if (!chunk) return NULL;
    if (ppool && *ppool)

cast void * to char * for pointer arithmetic

if ((char *)pchunk1->start + pchunk1->size == (char *)next->start)

Although (void *) and (char *) can be both equivalently cast to any other pointer type, it is only legal to perform pointer arithmetic on a (char *) and not with (void *) if you want to comply with Standard C.

When to use pointers of pointers ?

Compare

void change_head_pp(Node** _pphead, Node * _pnode)
{
    * pphead = node;
}

and

void change_head_p(Node* _phead, Node * _pnode)
{
     phead = node;
}

With the following code, which function changes the value of list_head ?

Node * phead = new_node();
Node * pnode = new_node();

change_head_p(phead, pnode);
change_head_pp(&phead, pnode);

Conclusion

If you want to change what a pointer points to or free the memory a pointer points to by use of a function, you need to input the address of that pointer (pointer to pointer) to the function.

How does this beautiful code work ?

void *_pool_malloc(Pool *self, size_t size)
{
    Chunk *chunk = find_chunk_by_size(self->unused, size);
    if (!chunk) return NULL;

    remove_chunk_from_list(chunk);
    if (chunk->size > size)
    {
        Chunk *new_chunk_node = new_chunk((char *)chunk->start + size, 
                            chunk->size - size);  // Renamed variable
        insert_chunk_to_list(self->unused, new_chunk_node);
        chunk->size = size;
    }
    
    insert_chunk_to_list(self->used, chunk);
    return chunk->start;
}

Further Readings on Memory Management

Java

Java uses a VM and Garbage Collectioin which uses alogoirthms such as Mark-and-Sweep.

JVM memory structure

Mark and Sweep

Rust

uses scope and single ownership

Linux

Linux is an operating system whose memory management (MM) needs to take care of processes and virtual memories ( memory mapped to the hard disk) and paging. MM is the most complex and important part of Linux Kernel. It is definitely much more complex than our ex02.

But if you have learned decent knowledge of Linux MM, you will be an export on C and embedded systems.

Last updated