1. Explain "#error"
所以他就只是一個丟出錯誤訊息的 macro 而已。
2. Explain "struct" and "union"
在 C 中,我們可以利用 struct 來定義自己要的資料結構,例如說二維坐標中的一個點,可以用 struct Point {int x, y;};
同樣的我們也可以用 union 做類似的事情,只是差別在於, union 中的每個成員是共用同樣的記憶體。
同樣的我們也可以用 union 做類似的事情,只是差別在於, union 中的每個成員是共用同樣的記憶體。
3. Explain "volatile". Can we use "const" and "volatile" in the same variable? Can we use "volatile" in a pointer?
volatile 是告訴 compiler 不要擅自對變數作最佳化。
參考以下的 code:
其中 x 在迴圈外被初始化成 FOO (的值),先不管 FOO 是什麼,在迴圈內 compiler 發現 *x = FOO; 可以做一下最佳化讓 *x 不要給值這麼多次以增加執行效率,所以可能忽略 *x = FOO; 做的事情。
但是如果 FOO 是一個硬體的記憶體位置,每次取值可能不同的結果,那 compiler 擅自做了最佳化以後就會造成 *x 只從硬體的記憶體位置中取值取一次 (int *x = FOO;),為了避免這種事情發生,可以利用 volatile 加在 x 宣告的時候:
那 const 可以跟 volatile 一起使用嗎?當然囉,這兩個 keyword 的意思並沒有牴觸。const 的意思是 read-only 而不是不變的,volatile 的意思是他可能會變而不是你可以改他。
參考以下的 code:
int *x = FOO;
for (int i = 0; i < 100; ++i) {
bar(i, x);
*x = FOO;
}
其中 x 在迴圈外被初始化成 FOO (的值),先不管 FOO 是什麼,在迴圈內 compiler 發現 *x = FOO; 可以做一下最佳化讓 *x 不要給值這麼多次以增加執行效率,所以可能忽略 *x = FOO; 做的事情。
但是如果 FOO 是一個硬體的記憶體位置,每次取值可能不同的結果,那 compiler 擅自做了最佳化以後就會造成 *x 只從硬體的記憶體位置中取值取一次 (int *x = FOO;),為了避免這種事情發生,可以利用 volatile 加在 x 宣告的時候:
volatile int *x = FOO;
那 const 可以跟 volatile 一起使用嗎?當然囉,這兩個 keyword 的意思並沒有牴觸。const 的意思是 read-only 而不是不變的,volatile 的意思是他可能會變而不是你可以改他。
4. For the following C code
unsigned long v1 = 0x 00001111;
unsigned long v2 = 0x 00001202;
unsigned long v;
v = v1&(~v2);
v = v | v2;
ask: the value of v?
最後一個 v 可以展開一下:
v = v | v2
= (v1 & (~v2)) | v2
= ( v1 | v2 ) & ( ~v2 | v2 )
因為 ~v2 | v2 等於 1,所以展開後
v = v1 | v2 = 0x00001111 | 0x00001202 = 0x0001313
v = v | v2
= (v1 & (~v2)) | v2
= ( v1 | v2 ) & ( ~v2 | v2 )
因為 ~v2 | v2 等於 1,所以展開後
v = v1 | v2 = 0x00001111 | 0x00001202 = 0x0001313
5. For the following C code
int a[5] ={1,2,3,4,5};
int *p = (int *)(&a+1);
ask: the value of *(a+1), (*p-1)?
*(a+1) 其實就是 a[1],所以就是 2;
(*p - 1) 就比較奇怪了,因為 (&a+1) 的關係所以 p 其實存的是 a[5] 的記憶體位置,
(*p - 1) 就比較奇怪了,因為 (&a+1) 的關係所以 p 其實存的是 a[5] 的記憶體位置,
(a_pointer + a_number) = (a_pointer + (a_number * sizeof(*a_pointer)))
所以 &a + 1 = &a + 1 * sizeof(*&a) = &a + 1 * 20 = a[5] (這邊是假設 int 大小是 4 bytes)所以理論上來說 *p 應該是 garbage,就算 - 1 以後還是 garbage ,答案應該是:不知道?
6. write a code
a. set the specific bit
b. clear the specific bit
c. inverse the specific bit (0->1; 1->0)
Macro 的解法:
b. clear the specific bit
c. inverse the specific bit (0->1; 1->0)
Macro 的解法:
a.
#define SET_BIT(x, n) ((x) |= (1 << (n)))
b. #define CLEAR_BIT(x, n) ((x) &= ~(1 << (n)))
c. #define INVERSE_BIT(x, n) ((x) ^= (1 << (n)))
Function 解法:
a.
static inline void set_bit(int *x, int n) { *x |= (1 << n); }
b. static inline void clear_bit(int *x, int n) { *x &= ~(1 << n); }
c. static inline void inverse_bit(int *x, int n) { *x ^= (1 << n); }
7. Fill the blank
void(*(*papf)[3])(char *); // Rewrite this
typedef ___________;
pf(*papf)[3];
第三行最後是用 pf 把 *papf 當作參數傳進去,所以把中間的 (*papf)[3] 取出來變成 pf:
typedef void(*pf)(char *);
8. Write a code that check the input is a multiple of 3 or not without using division or mod
最蠢的方式當然就是寫一個迴圈一直減 3 然後看最後是不是剩下 0 ... 但是超沒效率 XD"
直覺想到一個比較好一點的方式是把全部位數相加,如果總和大於 10 的話就繼續做全部位數相加,值到剩下一位數為止,然後看是不是 0, 3, 6, 9,是的話就是 3 的倍數。但是沒辦法用 mod 所以不曉得怎麼取得每個位數 ... 所以大概只能用 sprintf 吧 XD
但實際講起來 sprintf 大概也是有用到除法或者 mod 吧 ...
目前看到有個比較可行的做法是,在 N base 的系統中測試能否被 (N+1) 整除的方式是將偶數位數的和跟奇數位數的和相減,再看是否能被 N+1整除。最常見的例子就是 11 啦,不過那是因為是在 10 base 的系統中,所以在 2 base (也就是 2 進位啦) 的系統中可以用這種方式來判斷是否為 3 的倍數。
int multiple_of_three(int num) {
if (num < 0)
num = -num;
if (num == 0)
return 1; // true
if (num == 1 || num == 2)
return 0; // false
int even = 0, odd = 0;
while (num != 0) {
even += (num & 0x1);
num >>= 1;
odd += (num & 0x1);
num >>= 1;
}
return multiple_of_three(even - odd);
}
9. Explain lvalue and rvalue.
lvalue 跟 rvalue 分別指的是 = (等號) 的左邊跟右邊的值,但這樣講不太精確,因為 lvalue 跟 rvalue 描述的是 expression 而不是 object:
lvalue 可以 reference, rvalue 不能 reference。
C++03 3.10/1 says: "Every expression is either an lvalue or an rvalue." It's important to remember that lvalueness versus rvalueness is a property of expressions, not of objects
lvalue 可以 reference, rvalue 不能 reference。
沒有留言:
張貼留言