# 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