---
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 四層架構

#### 請解釋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;
};
```
####