Memory Allocate and Vector

on under study
5 minute read

The first time I learned about this is when I tried to create a bool array with 1000001 size in C++ to solve Baekjoon [17103][BOJ17103].

IDE suggested me to use malloc, which made me research, and thus, this is my code using that.

Dynamic Memory Allocate

const int LEN = 10;
int* pArr;
do pArr = (int*)malloc(sizeof(int) * LEN); while (pArr == NULL);
pArr[0] = 10;
*(pArr + 1) = 20;
if (pArr != NULL) { free(pArr); pArr = NULL; } // freeing memory

Hmmmm…?

I found something intriguing but I’ll talk more about that in the following post.

Vector

Or List<T> in C#.

The instructor said it’s equivalent of ArrayList, as many other blogs online have claimed, but in my experience, it is not.

ArrayList accepts any data type in it.

But List<T> accepts one data type for each, like vector.

(Calling that a vector is quite confusing, especially with Unity’s Vector2D which is a two float container)

Macro Function

#define SAFE_FREE(p)\
if (p) {\
        free(p);\
        (p) = NULL;\
    } // \ in the end of line joins the next line

I don’t think the instructor taught us the difference between macro function and normal one.

Macro function is NOT technically a function, but replaces itself its definition on Preprocessing.

This is why we’re using (p) instead of p.

#define MULTIFY(x,y) x*y
// ... //
printf("%d", MULTIFY(2 + 3, 3 + 2));
// => printf("%d", 2 + 3 * 3 + 2); => 13

In cases like this, as MULTIFY is converted to its definition on compile, the result may not be what we desire.

#define MULTIFY(x,y) (x)*(y)
// ... //
printf("%d", MULTIFY(2 + 3, 3 + 2));
// => printf("%d", (2 + 3) * (3 + 2)); => 25

Also, they do not care about the type of its parameters.

There are other things like # (converts to string) and ## (concat).

Create Array

void CreateArray(void** const _pArr, const size_t _size) {
    SAFE_FREE(*_pArr);
    do *_pArr = malloc(_size); while (*_pArr == NULL);
}

in C#, it’d be just new int[_size]; but in C, we need a lot of writing to just do that.

C may be faster for computer, but in the sense of programmers’ productivity, neigh.

Expand Array

void ExpandArray(int** _pArr, int* const _pArrLen) {
    int* newArr = NULL;
    CreateArray(&newArr, *_pArrLen * sizeof(int) * 2);
    for (int i = 0; i < *_pArrLen; ++i) newArr[i] = (*_pArr)[i]; // clone
    *_pArrLen *= 2;
    SAFE_FREE(*_pArr);
    *_pArr = newArr;
}

Or in C#, Array.Resize(ref arr, arr.Length * 2).

Obviously, if you need to use Array.Resize in C#, you’re doing this very wrong.

…or you’re a modder like me and trying to add new item to where it’s not supposed to.

Add and Print

void Add(int** _pArr, int* const _pArrLen, int* const _pIndex, const int _data) {
    if (*_pIndex >= *_pArrLen) ExpandArray(_pArr, _pArrLen);
    (*_pArr)[*_pIndex] = _data;
    ++(*_pIndex);
}

With ExpandArray being in separate function, the code is self-explanatory.

For naming functions, it is important that naming them for their intent, not how they work. You’d know how they work by looking at the code.

void Print(const int* _pArr, const int _index) {
    for (int i = 0; i < _index; ++i) printf("%d - ", _pArr[i]);
    printf("(%d)\n", _index);
}

Also this.

c, cpp, malloc, memory-allocate, data-structure, vector, macro