C programming: frequent questions and test-approved answers

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