C programming: frequent questions and test-approved answers

| category: Programming | author: st
Tags: ,

Q1. Difference between ++*p, *p++ and *++p

Priority to keep in mind:

  1. postfix ++
  2. prefix ++
  3. *
#include <stdio.h>
int main()
{
    int arr[] = {10, 20};
    int *p1 = arr;
    int *p2 = arr;
    int *p3 = arr;
    printf("arr[0] = %d, arr[1] = %d\n", arr[0], arr[1]);
    printf("arr[0] = %d, arr[1] = %d, *++p1 = %d\n", arr[0], arr[1], *++p1);
    printf("arr[0] = %d, arr[1] = %d, *p2++ = %d\n", arr[0], arr[1], *p2++);
    printf("arr[0] = %d, arr[1] = %d, *p2 = %d\n", arr[0], arr[1], *p2);
    ++*p3;
    printf("++*p3\narr[0] = %d, arr[1] = %d, *p3 = %d\n", arr[0], arr[1], *p3);
    return 0;
}
arr[0] = 10, arr[1] = 20
arr[0] = 10, arr[1] = 20, *++p1 = 20
arr[0] = 10, arr[1] = 20, *p2++ = 10
arr[0] = 10, arr[1] = 20, *p2 = 20
++*p3
arr[0] = 11, arr[1] = 20, *p3 = 11

Q2. Deep and shallow copies (object oriented style)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct
{
    char* first_name;
    char* last_name;
    int age;
} person;

person* person_create()
{
    person* result = (person*)malloc(sizeof(person));
    result->first_name = NULL;
    result->last_name = NULL;
    result->age = 0;
    return result;
}

void person_set_first_name(person* const self, const char* value)
{
    if (self->first_name)
        free(self->first_name);
    size_t len = strlen(value) + 1;
    self->first_name = (char*)malloc(len);
    strcpy_s(self->first_name, len, value);
}

void person_set_last_name(person* const self, const char* value)
{
    if (self->last_name)
        free(self->last_name);
    size_t len = strlen(value) + 1;
    self->last_name = (char*)malloc(len);
    strcpy_s(self->last_name, len, value);
}

person* person_create2(const char* first_name, const char* last_name, const int age)
{
    person* self = person_create();
    person_set_first_name(self, first_name);
    person_set_last_name(self, last_name);
    self->age = age;
    return self;
}

person* person_create_copy_shallow(const person* source)
{
    person* self = person_create();
    *self = *source;
    return self;
}

person* person_create_copy_deep(const person* source)
{
    person* self = person_create();
    person_set_first_name(self, source->first_name);
    person_set_last_name(self, source->last_name);
    self->age = source->age;
    return self;
}

void person_free(person** self)
{
    if ((*self)->first_name)
        free((*self)->first_name);
    if ((*self)->last_name)
        free((*self)->last_name);
    free(*self);
    *self = NULL;
}

void person_print(const person* self, const char* title)
{
    printf("%s:\n  First name: %s\n  Last name: %s\n  Age: %d\n",
        title, self->first_name, self->last_name, self->age);
}

int main(void)
{
    person *p1, *p2, *p3;
    const char* first_name1 = "John";
    const char* first_name2 = "James";
    const char* first_name3 = "Nathaniel";
    p1 = person_create2(first_name1, "Smith", 35);
    person_print(p1, "P1");
    p2 = person_create_copy_shallow(p1);
    person_print(p2, "P2 is a shallow copy of P1");
    person_set_first_name(p1, first_name2);
    p1->age = 40;
    puts("P1 first name and age has changed");
    person_print(p1, "P1");
    person_print(p2, "P2 name has changed too");
    p3 = person_create_copy_deep(p1);
    person_print(p3, "P3 is a deep copy of P1");
    person_set_first_name(p1, first_name3);
    p1->age = 45;
    puts("P1 first name and age has changed again");
    person_print(p1, "P1");
    person_print(p3, "P3 stays unchanged");
    person_free(&p1);
    free(p2); // Cannot use person_free(&p2) because of shallow coly
    person_free(&p3);
    return 0;
}
P1:
  First name: John
  Last name: Smith
  Age: 35
P2 is a shallow copy of P1:
  First name: John
  Last name: Smith
  Age: 35
P1 first name and age has changed
P1:
  First name: James
  Last name: Smith
  Age: 40
P2 name has changed too:
  First name: James
  Last name: Smith
  Age: 35
P3 is a deep copy of P1:
  First name: James
  Last name: Smith
  Age: 40
P1 first name and age has changed again
P1:
  First name: Nathaniel
  Last name: Smith
  Age: 45
P3 stays unchanged:
  First name: James
  Last name: Smith
  Age: 40