--- title: info2021-homework4 tags: INFO2021 --- # 2021 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2021)」課程作業 4 ## 自 [IC 產業結構和軟體工程師的機會](https://hackmd.io/@sysprog/BkE4X5vvF) 列出的 IC 設計公司的官方網站中,找出較符合自身興趣/規劃的職務描述 Lab是做網路的,研究方向為透過CPU SIMD指令與GPU平行計算加速IP Lookup及Packet Classification的演算法,都以C語言進行實作,由於沒有特別的自身興趣及煩惱許久仍沒有結論的職涯規劃,看了相關職務描述選擇以軟韌體開發相關職缺出發 ## 聯發科技 (4G/5G 系統軟體工程師) > 職缺說明 > 1. 訂定4G/5G 通訊系統使用的CPU及系統架構 > 2. 開發RTOS、記憶體管理等系統相關服務 > 3. 開發CPU及平台模擬器 > 4. 分析軟體行為並增進系統效能 > 5. 開發CPU及系統相關的驅動及開機流程 > 6. 開發自動診斷系統問題的工具 > > 職缺需求 > 1. 熟悉 C, 具 C++/Python 尤佳。 > 2. 具有 Driver 或 Kernel (任何 RTOS) 或 embedded system 相關開發經驗尤佳 ### Q: 分析上述職缺所需要的能力,探討自己在專業上匹配的程度 ### Q: 嘗試列出上述職缺 (或類似的職缺) 的面試題目,可以是網路搜尋整理,也可以自行改寫 在不揭露自身資訊的狀況下,比照第一次和第二次作業的問答形式,對面試題目進行問答,文字紀錄即可。避免只用教科書內容回答,儘量搭配自己過去 (或近期學習到) 的程式開發經驗,進行自問自答 #### 十進制轉二進制有幾個1 ``` clike= void numofone(int k){ int count = 0; while(k){ if(k&1) count++; k = k>>1; } printf("count: %d\n",count); } int main(void) { int k = 0x80000000;//負數會錯 numofone(k); return 0; } ``` ``` clike= void numofone(int k){ int count = 0; unsigned int flag = 1; while(flag){ if(k&flag) count++; flag = flag<<1; } printf("count: %d\n",count); } int main(void) { int k = 0x80000000; numofone(k); return 0; } ``` ``` clike= void numofone(unsigned int k){ int count = 0; while(k){ count++; k = k & (k-1);//k若為int,則負數時會overflow } printf("count: %d\n",count); } int main(void) { unsigned int k = 0x80000000; numofone(k); return 0; } ``` #### 請說明 OSI 七層架構及 TCP/IP 四層架構 ![](https://i.imgur.com/Rrbyghn.png) #### 請解釋C語言內的 **#error** - #error預處理程序指令用於指示錯誤。如果找到#error指令編譯器將發出致命錯誤,跳過進一步的編譯過程 ``` cpp #include <stdio.h> #ifdef __cplusplus //c++編譯器 #error 請使用g++,不能用gcc #endif ``` #### 請說明 **struct** and **union** 的差異 - union 所有成員共享同一塊記憶體,對其中一個成員賦值會覆蓋原先記憶體內存在的值,struct 則與之相反,故 union 適合應用在記憶體比較吃緊的設備或場景下 #### 什麼是 **const**, **static**, **volatile** - const - 欲阻止一個變數被改變,可使用const,在定義該const變數時,需先初始化,以後就沒有機會改變他了 - 對指標而言,可以指定指標本身為const,也可以指定指標所指的資料為const,或二者同時指定為const - 在一個函式宣告中,const可以修飾形參表明他是一個輸入引數,在函式內部不可以改變其值 - static - static區域性變數在函式內定義,它的生存期為整個源程式,但是其作用域仍與自動變數相同,只能在定義該變數的函式內使用該變數。退出該函式後, 儘管該變數還繼續存在,但不能使用它 - static修飾全域性變數的時候,這個全域性變數只能在本檔案中訪問,不能在其它檔案中訪問,即便是extern外部宣告也不可以 - static修飾一個函式,則這個函式的只能在本檔案中呼叫,不能被其他檔案呼叫。Static修飾的區域性變數存放在全域性資料區的靜態變數區。初始化的時候自動初始化為0 - volatile - 一個定義為volatile的變數是說這變數可能會被意想不到地改變,這樣,編譯器就不會去假設這個變數的值了。精確地說就是,優化器在用到這個變數時必須每次都小心地重新讀取這個變數的值,而不是使用儲存在暫存器裡的備份 #### 什麼是 **call by value**, **call by address**, **call by reference** - call by value ``` clike= int main() { int a = 1 ; int b = a ; //將a的值複製到b的新記憶體區域 return 0; } ``` - call by address ``` clike= void swap(int *address_a, int *address_b) { int temp = *address_a ; *address_a = *address_b; *address_b = temp; } int main() { int a = 1; int b = 0; printf("%d %d\n", a, b);// 1 0 swap(&a, &b); // 傳入a, b的address進行交換 printf("%d %d\n", a, b);// 0 1 return 0; } ``` - call by reference C 並沒有 call by reference,C++才有提供 ``` clike= void swap(int &address_a, int &address_b) { int temp = address_a ; address_a = address_b; address_b = temp; } int main() { int a = 1; int b = 0; cout<< a << " " << b << endl; // 1 0 swap(a, b); // 傳入a, b的address進行交換 cout<< a << " " << b << endl; // 0 1 return 0; } ``` #### Swap without extra memory ``` clike= void xorswap(int *x, int *y) { *x ^= *y; *y ^= *x; *x ^= *y; } ``` #### Reverse integer bitwise without using loop ``` clike= int reverse_bits(int x) { x = ((x & 0xffff0000) >> 16) | ((x & 0x0000ffff) << 16); x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8); x = ((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4); x = ((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2); x = ((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1); return x; } ``` #### 判斷一個數是不是2的冪 ``` clike= int check(int x){ return (x & -x) == x); } ``` #### 計算有幾個位元是1 ``` clike= int count_bits(x){ x = (x & 0x55555555) + ((x & 0xaaaaaaaa) >> 1); x = (x & 0x33333333) + ((x & 0xcccccccc) >> 2); x = (x & 0x0f0f0f0f) + ((x & 0xf0f0f0f0) >> 4); x = (x & 0x00ff00ff) + ((x & 0xff00ff00) >> 8); x = (x & 0x0000ffff) + ((x & 0xffff0000) >> 16); return x; } ``` #### 請舉出 mutex 實際例子 ``` clike= #include <stdio.h> #include <pthread.h> pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; #define LOOPS 100000 int counter = 0; void *inc(){ for (int i=0; i<LOOPS; i++) { pthread_mutex_lock(&mutex1); counter = counter + 1; pthread_mutex_unlock(&mutex1); } } void *dec(){ for (int i=0; i<LOOPS; i++) { pthread_mutex_lock(&mutex1); counter = counter - 1; pthread_mutex_unlock(&mutex1); } } int main() { pthread_t thread1, thread2; pthread_create(&thread1, NULL, inc, NULL); pthread_create(&thread2, NULL, dec, NULL); pthread_join(thread1, NULL); pthread_join(thread2, NULL); printf("counter=%d\n", counter); } ``` #### Explain lvalue and rvalue - 左值 (lvalue) : 一個佔據某個特定記憶體的值。 - 右值 (rvalue) : 一個 expression 結束後就消失的值。 #### the value of *(a+1), *(p-1) ``` clike= int main() { int a[5] = {1,2,3,4,5}; int *p = (int *)(&a+1); printf("*(a+1): %d\n", *(a+1));//2 printf("*(p-1): %d\n", *(p-1));//5 return 0; } ``` #### 全域變數、區域變數未初始化會是什麼值 - 全域變數、靜態變數初值為0 - 區域變數存在stack中,stack反覆被利用,若沒有初始化值就是髒的 #### Data type - int a; // An integer - int *a; // A pointer to an integer - int **a; // A pointer to a pointer to an integer - int a[10]; // An array of 10 integers - int *a[10]; // An array of 10 pointers to integers - int (*a)[10]; // A pointer to an array of 10 integers - int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer - int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer #### j = ? - macro 會替代原程式碼的部分,故要注意loop的scope ``` clike= #define INC(x) x*=2; x+=1 int main(){ int i, j; for(i=0,j=1;i<5;i++) INC(j); printf("%d\n",j); //33 return 0; } ``` ### 實際面試問題 #### 計算 struct 大小 ``` clike= struct A { //sizeof(struct A) = 8 char a; short b; int c; }; ``` ``` clike= struct A { //sizeof(struct A) = 12 char a; int b; short c; }; ``` ####