Week01 Lab Notes

Creating a Vector

Vector allocated on the heap

Vector * pv = (Vector *) malloc(sizeof(Vector));

// need to change block_size  from const size_t to size_t
pv->block_size = BLOCK_SIZE;
// initialisation
pv->capacity = pv->block_size;
pv->data = (int *) malloc(pv->capacity * sizeof(int) );
pv->size = 0;
//...

allocated on the stack

Vector vector = {
	.block_size = BLOCK_SIZE,
	.size = 0
	// ...
};

Boolean Type

bool was introduced in C99

// recommended to use bool instead of int to represent a boolean

// recommended to reuse 
// bool contains(Set* set, int val)
// in add_memeber() and remove_memeber()
void add_member(Set* set, int val){
	int exists = 0;
	for(int i = 0;i<set->size;i++){
		if(set->data[i]==val){
			exists = 1;
			printf("value already in set\n");
		}
	}
	if(!exists){
	  // add the member
	  // ...
	}
}

Using of pointers

Use -> for pointers

Vector * pv = NULL;
(*pv).size = 0;

pv->size = 0;
memmove(((*pv).data + pos), ((*pv).data + pos + 1), ((*pv).size - pos) * sizeof(int));

Array name is the pointer to the first element

int arr[5];

// arr == & arr[0];
// arr + 1 == & arr[1]

int * p = arr;
// the real offset is 2 * sizeof(int)
* (p + 2 ) = arr[2];

// pv->data == & pv->data[0]
Vector * pv;

// statement 1
* (pv->data + pos) = val ;

// statement 2 is equivalent to statement 1
// statement 2
pv->data[pos] = val; 
(int*)memmove(&pv->data[pos + 1], &pv->data[pos], (pv->size - pos) * sizeof(int));

// can be better written as
memmove(pv->data + pos + 1, pv->data + pos, (pv->size - pos) * sizeof(int));
memmove(&set->data[pos],&set->data[pos+1],(set->size-pos)* sizeof(int));

// can be written as 
memmove(set->data + pos, set->data + pos + 1, (set->size - pos) * sizeof(int));
if ((*sv2).contains(sv2, *((*sv1).data + i)) == false)
{
    return false;
}

// can be better written as
if (! sv2->contains(sv2, sv1->data[i]))
{
    return false;
}

Swap

Only one temp variable is needed

int temp = get(pv, pos1);
set(pv, pos1, get(pv, pos2));
set(pv, pos2, temp);

Two temps are not bad as the code is more readable and the compiler will do the optimisation for you.

int temp1 = get(pv, pos1);
int temp2 = get(pv, pos2);
set(pv, pos1, temp2);
set(pv, pos2, temp1);

Can we use memcmp for equals() of a Vector

might be OK for our implemention whose data always starts from pv->data[0]

bool equals(Vector * pv1, Vector * pv2)
{
    if (pv1->size != pv2->size)
    {
        return false;
    }
    
    return 0 == memcmp(pv1->data, pv2->data);
}

Note: The equals() of Java objects is not an easy topic

Coding Style

Spaces

Recommended to add space inbetween to improve readability. For example you should add a space before and after an operator (with the exception of ++ and --).

// not very good
if(set->data[i]==val){
	return true;
}

// better
if (set->data[i] == val) {
	return true;
}

// or 
if (set->data[i] == val) 
{
	return true;
}
// not very good
if (set->size-1 == set->capacity-set->block_size) {
    set->data = realloc(set->data,(set->capacity-set->block_size)*sizeof(int));
    set->capacity-=set->block_size;
}
set->size--;

// better
if (set->size - 1 == set->capacity - set->block_size) {
    set->data = realloc(set->data, (set->capacity - set->block_size) * sizeof(int));
    set->capacity -= set->block_size;
}
set->size--;

Braces for if ?

It is recommended to use braces around for, if, while statements

if (set->data[i] == val) 
	return true;

if (set->data[i] == val) 
{
	return true;
}

An example from https://wiki.sei.cmu.edu/confluence/display/c/EXP19-C.+Use+braces+for+the+body+of+an+if%2C+for%2C+or+while+statement

if (invalid_login())
  login = 0;
else
  printf("Login is valid\n");  /* Debugging line added here */
  login = 1;

Dangling if else in C, C++, Java

// ambiguity without braces
// the compiler will treat it as follows the innermost if
if (ch >= 3) 
    if (ch <= 10) 
        k++;
    else
        o++;

// if you like the else follows the outer if
if (ch >= 3) 
{
    if (ch <= 10) 
        k++;
}
else
{
    o++;
}

Making == comparisons

Vector * pv;
if (pv == NULL) 
{
    return -1;
}

// a better practice, fails to compile when you write
// if (NULL = pv)
if (NULL ==  pv)
{
    return -1;
}
if(set->size == 0){
    return true;
}

// better
// fails to compile with if (0 = set->size)
if (0 == set->size) {
    return true;
}

About ++ --

Some people don't like ++ — as they are confusing

int a = 1;

b = a++;

// or 
b = ++a;

// I think it is OK in for loop
for (int i = 0; i < 10; i++)
{
    // ...
}

Last updated