7.void*和C結構體
問:你能設計一個能接受任何類型的參數並返回interger(整數)結果的函數嗎?
答:如下:
- int func(void *ptr)
如果這個函數的參數超過一個,那麼這個函數應該由一個結構體來調用,這個結構體可以由需要傳遞參數來填充。
8.*和++操作
問:下面的操作會輸出什麼?爲什麼?
- #include<stdio.h>
- int main(void)
- {
- char *ptr = "Linux";
- printf("\n [%c] \n",*ptr++);
- printf("\n [%c] \n",*ptr);
- return 0;
- }
答:輸出結果應該是這樣:
- [L]
- [i]
因爲“++”和“*”的優先權一樣,所以“*ptr++”相當於“*(ptr++)”。即應該先執行ptr++,然後纔是*ptr,所以操作結果是“L”。第二個結果是“i”。
9.問:修改代碼片段(或者只讀代碼)
問:下面的代碼段有錯,你能指出來嗎?
- #include<stdio.h>
- int main(void)
- {
- char *ptr = "Linux";
- *ptr = 'T';
- printf("\n [%s] \n", ptr);
- return 0;
- }
答:這是因爲,通過*ptr = ‘T’,會改變內存中代碼段(只讀代碼)“Linux”的第一個字母。這個操作是無效的,因此會造成seg-fault或者崩潰。
10.會改變自己名字的進程
問:你能寫出一個在運行時改變自己進程名的程序嗎?
答:參見下面這段代碼:
- #include<stdio.h>
- int main(int argc, char *argv[])
- {
- int i = 0;
- char buff[100];
- memset(buff,0,sizeof(buff));
- strncpy(buff, argv[0], sizeof(buff));
- memset(argv[0],0,strlen(buff));
- strncpy(argv[0], "NewName", 7);
- // Simulate a wait. Check the process
- // name at this point.
- for(;i<0xffffffff;i++);
- return 0;
- }
11.返回本地變量的地址
問:下面代碼有問題嗎?如果有,該怎麼修改?
- #include<stdio.h>
- int* inc(int val)
- {
- int a = val;
- a++;
- return &a;
- }
- int main(void)
- {
- int a = 10;
- int *val = inc(a);
- printf("\n Incremented value is equal to [%d] \n", *val);
- return 0;
- }
答:儘管上面的程序有時候能夠正常運行,但是在“inc()”中存在嚴重的漏洞。這個函數返回本地變量的地址。因爲本地變量的生命週期就是“inc()”的生命週期,所以在inc結束後,使用本地變量會發生不好的結果。這可以通過將main()中變量“a”的地址來避免,這樣以後還可以修改這個地址存儲的值。
12.處理printf()的參數
問:下面代碼會輸出什麼?
- #include<stdio.h>
- int main(void)
- {
- int a = 10, b = 20, c = 30;
- printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));
- return 0;
- }
答:輸出結果是:
- 110..40..60
這是因爲C語言裏函數的參數默認是從右往左處理的,輸出時是從左往右。
原文鏈接:the Geek Stuff