What happens if an object of struct type is not explicitly initialized?
struct Student gStu;
int main(void) {
struct Student stu;
}
What happens if an object of struct type is not explicitly initialized?
struct Student gStu;
int main(void) {
struct Student stu;
}
static: "empty-initialization", which performs member-wise empty-initialization.static: every member is initialized to indeterminate values (in other words, uninitialized).Use an initializer list:
struct Student stu = {"Alice", "2024533000", 2024, 8};
Use C99 designators: (highly recommended)
struct Student stu = {.name = "Alice", .id = "2024533000",
.entrance_year = 2024, .dorm = 8};
The designators greatly improve the readability.
[Best practice] Use designators, especially for struct types with lots of members.
struct Student *student_list = malloc(sizeof(struct Student) * n);
for (int i = 0; i != n; ++i) {
student_list[i].name = A(i); // A, B, C and D are some functions
student_list[i].id = B(i);
student_list[i].entrance_year = C(i);
student_list[i].dorm = D(i);
}
Use a compound literal to make it clear and simple:
struct Student *student_list = malloc(sizeof(struct Student) * n);
for (int i = 0; i != n; ++i) {
student_list[i] = (struct Student){.name = A(i), .id = B(i),
.entrance_year = C(i), .dorm = D(i)};
}
struct-typed parametersThe semantic of argument passing is copy:
void print_student(struct Student s) {
printf("Name: %s, ID: %s, dorm: %d\n", s.name, s.id, s.dorm);
}
print_student(student_list[i]);
In a call print_student(student_list[i]), the parameter s of print_student is initialized as follows:
struct Student s = student_list[i];
The copy of a struct-typed object: Member-wise copy.
struct-typed parametersIn a call print_student(student_list[i]), the parameter s of print_student is initialized as follows:
struct Student s = student_list[i];
The copy of a struct-typed object: Member-wise copy. It is performed as if
s.name = student_list[i].name;
s.id = student_list[i].id;
s.entrance_year = student_list[i].entrance_year;
s.dorm = student_list[i].dorm;
struct-typed objectStrictly speaking, returning is also a copy:
struct Student fun(void) {
struct Student s = something();
some_operations(s);
return s;
}
student_list[i] = fun();
The object s is returned as if
student_list[i] = s;
But in fact, the compiler is more than willing to optimize this process. We will talk more about this in C++.
struct A {
int array[10];
// ...
};
Although an array cannot be copied, an array member can be copied.
The copy of an array is element-wise copy.
int a[10];
int b[10] = a; // Error!
struct A a;
struct A b = a; // OK
A struct is a type consisting of a sequence of members.
Member access: obj.mem, ptr->mem (equivalent to (*ptr).mem, but better)
sizeof(struct A), no less than the sum of size of every member.
Implicit initialization: recursively performed on every member.
Initializer-lists, designators, compound literals.
Copy of a struct: member-wise copy.
Argument passing and returning: copy.
Consider a 3-d coordinate point structs to represent these concepts.
Write some functions to calculate the distance between points and lines, to calculate the point
Learn and try to use initializer-lists, designators and compound literals.
double dist(struct Point3d p, struct Line3d line);
struct Point3d line_at(struct Line3d line, double t);
A piece of cake!
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; ++i)
result *= i;
return result;
}
You should be able to write this in 30 seconds.
Consider the recurrence relation:
Translate it directly into C:
int factorial(int n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
This is perfectly valid and reasonable C code!
factorial recursively calls itself.
If we only have getchar, how can we read an integer?
If we only have putchar, how can we print an integer?
<stdio.h>.putchar(c) prints a character c. That's it.For convenience, suppose the integer is non-negative (unsigned).
To print
void print(unsigned x) {
if (x < 10)
putchar(x + '0'); // Remember ASCII?
else {
print(x / 10);
putchar(x % 10 + '0');
}
}
To print
void print(unsigned x) {
if (x >= 10)
print(x / 10);
putchar(x % 10 + '0');
}
Suppose we are given a problem of scale
* Feels like mathematical induction?
Calculate
Calculate
unsigned long long quick_power(unsigned long long x, int n) {
if (n == 0)
return 1;
if (n % 2 == 1)
return x * quick_power(x, n - 1);
else {
unsigned long long t = quick_power(x, n / 2);
return t * t;
}
}
How do you sort a sequence of
Do it recursively.
How do you sort a sequence of
Do it recursively: Suppose we are going to sort
Do it recursively: Suppose we are going to sort
void sort_impl(int *a, int k, int n) { // "impl" stands for "implementation"
}
void sort(int *a, int n) {
sort_impl(a, 0, n); // Why do we set k = 0 here?
}
Do it recursively: Suppose we are going to sort
void sort_impl(int *a, int k, int n) {
if (k == n - 1)
return;
}
Do it recursively: Suppose we are going to sort
void sort_impl(int *a, int k, int n) {
if (k == n - 1)
return;
int m = k;
for (int i = k + 1; i < n; ++i)
if (a[i] < a[m])
m = i;
}
Do it recursively: Suppose we are going to sort
void sort_impl(int *a, int k, int n) {
if (k == n - 1) return;
int m = k;
for (int i = k + 1; i < n; ++i)
if (a[i] < a[m]) m = i;
swap(&a[m], &a[k]); // the "swap" function we defined in previous lectures
}
Do it recursively: Suppose we are going to sort
void sort_impl(int *a, int k, int n) {
if (k == n - 1) return;
int m = k;
for (int i = k + 1; i < n; ++i)
if (a[i] < a[m]) m = i;
swap(&a[m], &a[k]); // the "swap" function we defined in previous lectures
sort_impl(a, k + 1, n); // sort the rest part recursively
}
void sort_impl(int *a, int k, int n) {
if (k == n - 1)
return;
int m = k;
for (int i = k + 1; i < n; ++i)
if (a[i] < a[m])
m = i;
swap(&a[m], &a[k]); // the "swap" function we defined in previous lectures
sort_impl(a, k + 1, n); // sort the rest part recursively
}
void sort(int *a, int n) {
sort_impl(a, 0, n);
}