# previous exam
## call by refence & bit set
```c
#define SET_BIT(x,n) ((x) |= (1<<(n)))
#define CLEAR_BIT(x,n) ((x) &= ~(1<<(n)))
void swap(int *num1, int *num2){
int temp = *num1;
*num1 = *num2;
*num2 = temp;
}
int main(){
int a = 1,b = 2;
swap(&a,&b);
int a[3],b[5];
swap(&a,&b);
int c = 1;
SET_BIT(c,3);//001001
CLEAR_BIT(c,1);//001000
}
```
## Linked List swap
Leetcode有這題。
這段代碼創建了一個包含四個節點的鏈表:1->2->3->4。然後使用 swapPairs() 函數交換相鄰節點的值。最後,列印鏈表內容,結果為 2->1->4->3。
```c
#include <stdio.h>
#include <stdlib.h>
// 定義鏈表節點結構體
struct Node {
int data;
struct Node* next;
};
// 交換相鄰節點的值
void swapPairs(struct Node* head) {
struct Node* temp = head;
while (temp != NULL && temp->next != NULL) {
// 交換相鄰節點的值
int temp_data = temp->data;
temp->data = temp->next->data;
temp->next->data = temp_data;
// 指針移到下一組相鄰節點
temp = temp->next->next;
}
}
// 輸出鏈表內容
void printList(struct Node* node) {
while (node != NULL) {
printf("%d ", node->data);
node = node->next;
}
printf("\n");
}
// 創建新節點
struct Node* newNode(int data) {
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->data = data;
node->next = NULL;
return node;
}
int main() {
// 創建鏈表 1->2->3->4
struct Node* head = newNode(1);
head->next = newNode(2);
head->next->next = newNode(3);
head->next->next->next = newNode(4);
printf("Original list: ");
printList(head);
// 交換相鄰節點
swapPairs(head);
printf("After swapping: ");
printList(head);
return 0;
}
```
## 列出所有memory type
RAM(隨機存取記憶體):用於臨時存儲資料和程式,其內容在斷電後會丟失。
ROM(唯讀記憶體):包括固化在晶片上的程式和資料,內容在斷電後不會丟失,只能讀取不能寫入。
Cache(緩存):位於CPU和主存之間,用於臨時存儲常用的資料和指令,以提高存取速度。
Flash Memory(快閃記憶體):一種非易失性記憶體,常見於USB驅動器、固態硬碟、SD卡等設備中。
EEPROM(電可擦可程式設計唯讀記憶體):一種非易失性記憶體,可以被擦除和重新程式設計,用於存儲固件和配置資料。
Register(寄存器):位於CPU內部的最快速的記憶體,用於存儲指令、資料和位址等臨時資訊。
Virtual Memory(虛擬記憶體):利用硬碟空間作為RAM的擴展,用於管理程式和資料的記憶體訪問。
DRAM(動態隨機存取記憶體):一種常見的RAM類型,用於電腦的主記憶體。
SRAM(靜態隨機存取記憶體):另一種RAM類型,比DRAM速度快但成本更高,常見於緩存和高性能應用。
voltaile memory
non-voltaile memory
"volatile memory" 是指在電腦中臨時存儲資料的一種記憶體類型,其特點是資料在斷電後會丟失。它通常用於存儲臨時資料,如程式執行時的變數、緩存等。RAM(隨機存取記憶體)就是一種volatile memory。
"non-volatile memory" 則是指在電腦中存儲資料的另一種記憶體類型,其特點是資料在斷電後不會丟失,即使沒有電源供應,資料仍然保持。這種記憶體用於長期存儲資料,如硬碟驅動器、固態硬碟、快閃記憶體等。
簡而言之,volatile memory 是臨時記憶體,非永久性的,而 non-volatile memory 則是持久性的,資料可以長期保存。
甚麼是DMA?
DMA是「直接記憶體存取」的縮寫,是一種計算機技術,允許外部設備直接存取系統內存,而無需經過中央處理器(CPU)。這可以提高數據傳輸效率和系統性能。
## 甚麼是race condition?
競爭條件是多個進程或線程競爭共用資源的情況,導致結果取決於執行順序。例如,兩個線程同時訪問並更改相同的變量,可能導致意外的結果,如數據錯誤或系統崩潰。
補充(甭寫):
```c
#include <stdio.h>
#include <pthread.h>
int shared_variable = 0;
// 這是兩個線程都會運行的函數
void *increment(void *arg) {
int i;
for (i = 0; i < 1000000; i++) {
shared_variable++; // 將共用變量增加1000000次
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 創建兩個線程來執行increment函數
pthread_create(&thread1, NULL, increment, NULL);
pthread_create(&thread2, NULL, increment, NULL);
// 等待兩個線程完成
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
// 列印共用變量的最終值
printf("Final value of shared_variable: %d\n", shared_variable);
return 0;
}
```
在這個例子中,兩個線程同時增加一個全域變量 shared_variable 的值。由於沒有對這個變量的訪問進行同步,因此可能會發生競爭條件。運行多次該程式可能會得到不同的最終值,這就是競爭條件的結果。
## 甚麼是dead lock?
鎖死是多個進程或線程彼此等待對方所持有的資源,導致所有進程都無法繼續執行的情況。
舉例:
兩個進程分別持有A和B兩個資源,但同時等待對方釋放另一個資源。
補充(甭寫):
```
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void *thread1_function(void *arg) {
pthread_mutex_lock(&mutex1); // 執行緒1獲取mutex1
printf("Thread 1 acquired mutex1\n");
// 延時,增加鎖死發生的機會
sleep(1);
pthread_mutex_lock(&mutex2); // 嘗試獲取mutex2
printf("Thread 1 acquired mutex2\n");
pthread_mutex_unlock(&mutex2); // 釋放mutex2
pthread_mutex_unlock(&mutex1); // 釋放mutex1
return NULL;
}
void *thread2_function(void *arg) {
pthread_mutex_lock(&mutex2); // 執行緒2獲取mutex2
printf("Thread 2 acquired mutex2\n");
// 延時,增加鎖死發生的機會
sleep(1);
pthread_mutex_lock(&mutex1); // 嘗試獲取mutex1
printf("Thread 2 acquired mutex1\n");
pthread_mutex_unlock(&mutex1); // 釋放mutex1
pthread_mutex_unlock(&mutex2); // 釋放mutex2
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 創建兩個執行緒分別執行 thread1_function 和 thread2_function
pthread_create(&thread1, NULL, thread1_function, NULL);
pthread_create(&thread2, NULL, thread2_function, NULL);
// 等待兩個執行緒結束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
```
以下是一個簡單的C代碼示例,展示了鎖死的情況:
```c
#include <stdio.h>
#include <pthread.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void *thread1_function(void *arg) {
pthread_mutex_lock(&mutex1); // 執行緒1獲取mutex1
printf("Thread 1 acquired mutex1\n");
// 延時,增加鎖死發生的機會
sleep(1);
pthread_mutex_lock(&mutex2); // 嘗試獲取mutex2
printf("Thread 1 acquired mutex2\n");
pthread_mutex_unlock(&mutex2); // 釋放mutex2
pthread_mutex_unlock(&mutex1); // 釋放mutex1
return NULL;
}
void *thread2_function(void *arg) {
pthread_mutex_lock(&mutex2); // 執行緒2獲取mutex2
printf("Thread 2 acquired mutex2\n");
// 延時,增加鎖死發生的機會
sleep(1);
pthread_mutex_lock(&mutex1); // 嘗試獲取mutex1
printf("Thread 2 acquired mutex1\n");
pthread_mutex_unlock(&mutex1); // 釋放mutex1
pthread_mutex_unlock(&mutex2); // 釋放mutex2
return NULL;
}
int main() {
pthread_t thread1, thread2;
// 創建兩個執行緒分別執行 thread1_function 和 thread2_function
pthread_create(&thread1, NULL, thread1_function, NULL);
pthread_create(&thread2, NULL, thread2_function, NULL);
// 等待兩個執行緒結束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
```
在這個例子中,執行緒1嘗試獲取mutex1,然後等待1秒。而在此時,執行緒2已經獲取了mutex2,並等待1秒。接著,執行緒1嘗試獲取mutex2,而執行緒2嘗試獲取mutex1,由於各自持有的mutex被對方所佔用,兩個執行緒都無法繼續執行,導致鎖死的發生。
## 其他建議
https://hackmd.io/@jQSlhiN3QaGkugpbD4NDAA/rkvNkyQfi
https://medium.com/%E6%8A%80%E8%A1%93%E7%AD%86%E8%A8%98/%E5%9F%BA%E7%A4%8E%E6%BC%94%E7%AE%97%E6%B3%95%E7%B3%BB%E5%88%97-%E5%9F%BA%E7%A4%8E%E8%B3%87%E6%96%99%E7%B5%90%E6%A7%8B-linked-list-%E8%88%87-array-553cb926029f
https://hackmd.io/@SupremeEJ/SkcsCUGh8